package ui import raylib "vendor:raylib" import assets "../assets" import audio "../audio" import themes "../themes" Font_Style :: assets.Font_Style TEXT_SPACING :: 1 @(private) any_hovered: bool // Call at the start of each frame's drawing begin_frame :: proc() { any_hovered = false } // Call at the end of each frame's drawing end_frame :: proc() { raylib.SetMouseCursor(any_hovered ? .POINTING_HAND : .DEFAULT) } // Mark that something clickable is under the mouse (shows the hand cursor) set_hovered :: proc() { any_hovered = true } measure_text :: proc(text: cstring, size: f32, style: Font_Style = .REGULAR) -> raylib.Vector2 { return raylib.MeasureTextEx(assets.get_font(style), text, size, TEXT_SPACING) } draw_text :: proc(text: cstring, pos: raylib.Vector2, size: f32, color: raylib.Color, style: Font_Style = .REGULAR) { raylib.DrawTextEx(assets.get_font(style), text, pos, size, TEXT_SPACING, color) } // Draws text horizontally centered on center_x with its top at y draw_text_centered :: proc(text: cstring, center_x, y, size: f32, color: raylib.Color, style: Font_Style = .REGULAR, shadow := false) { w := measure_text(text, size, style).x pos := raylib.Vector2{center_x - w / 2, y} if shadow { draw_text(text, pos + {0, size * 0.05}, size, raylib.Fade(themes.BLACK, 0.18), style) } draw_text(text, pos, size, color, style) } // Draws text centered in a rectangle draw_text_in_rect :: proc(text: cstring, rect: raylib.Rectangle, size: f32, color: raylib.Color, style: Font_Style = .REGULAR) { dims := measure_text(text, size, style) pos := raylib.Vector2{rect.x + (rect.width - dims.x) / 2, rect.y + (rect.height - dims.y) / 2} draw_text(text, pos, size, color, style) } draw_title :: proc(text: cstring, y: f32, color: raylib.Color, size: f32 = themes.TITLE_FONT_SIZE) { draw_text_centered(text, themes.SCREEN_WIDTH / 2, y, size, color, style = .BOLD, shadow = true) } // A rounded button with hover, press and shadow states. Returns true when clicked // or when its hotkey is pressed. button :: proc(rect: raylib.Rectangle, text: cstring, color: raylib.Color, text_color := themes.WHITE, font_size: f32 = themes.BUTTON_FONT_SIZE, hotkey := raylib.KeyboardKey.KEY_NULL, selected := false) -> bool { hovered := raylib.CheckCollisionPointRec(raylib.GetMousePosition(), rect) pressed := hovered && raylib.IsMouseButtonDown(.LEFT) if hovered { set_hovered() } lift: f32 = 0 fill := color if hovered { lift = 2 fill = raylib.ColorBrightness(color, 0.12) } if pressed { lift = -1 fill = raylib.ColorBrightness(color, -0.08) } shadow := raylib.Rectangle{rect.x, rect.y + 4, rect.width, rect.height} raylib.DrawRectangleRounded(shadow, 0.4, 12, raylib.Fade(themes.BLACK, 0.18)) body := raylib.Rectangle{rect.x, rect.y - lift, rect.width, rect.height} raylib.DrawRectangleRounded(body, 0.4, 12, fill) if selected { ring := raylib.Rectangle{body.x - 4, body.y - 4, body.width + 8, body.height + 8} raylib.DrawRectangleRoundedLinesEx(ring, 0.4, 12, 3, color) } draw_text_in_rect(text, body, font_size, text_color, style = .BOLD) clicked := hovered && raylib.IsMouseButtonPressed(.LEFT) if hotkey != .KEY_NULL && raylib.IsKeyPressed(hotkey) { clicked = true } if clicked { audio.play(.CLICK) } return clicked }