Ragnarokkr/menu_list.odin

122 lines
2.7 KiB
Odin
Raw Normal View History

2024-10-04 21:16:58 +03:00
package main
import rl "vendor:raylib"
import "core:math/ease"
import "core:fmt"
MenuItemType :: enum {
NONE,
BOOL,
INT,
}
BoolStrings := map[bool]cstring {
true = "вкл",
false = "выкл"
}
MenuItem :: struct{
text: cstring,
param: rawptr,
type: MenuItemType,
}
2024-10-04 21:16:58 +03:00
MenuList :: struct($T: typeid) {
state: ^GameState,
position: vec2,
line_size: f32,
font_size: f32,
active_element: T,
active_marker: vec2,
tween: ^Tween,
elements: ^[T]MenuItem,
2024-10-04 21:16:58 +03:00
menu_pressed: proc(state: ^GameState, element: T),
background: rl.Color,
mouse_pos: vec2,
}
menu_list_update :: proc(list: ^MenuList($T)) {
activate_element := false
prev_element := cast(i8)list.active_element
cur_element := prev_element
last_mouse_pos := list.mouse_pos
list.mouse_pos = rl.GetMousePosition()
size := menu_list_get_size(list)
if rl.CheckCollisionPointRec(list.mouse_pos, rl.Rectangle{
x = list.position.x,
y = list.position.y,
width = size.x,
height = size.y,
}) {
if last_mouse_pos != list.mouse_pos {
mouse_relative := list.mouse_pos - list.position
cur_element = i8(mouse_relative.y / list.line_size)
}
if rl.IsMouseButtonPressed(rl.MouseButton.LEFT) {
list.menu_pressed(list.state, list.active_element)
}
}
last_mouse_pos = list.mouse_pos
if rl.IsKeyPressed(rl.KeyboardKey.DOWN) {
cur_element += 1
}
if rl.IsKeyPressed(rl.KeyboardKey.UP) {
cur_element -= 1
}
if prev_element != cur_element {
if cur_element < 0 { cur_element = len(T) -1 }
if cur_element == len(T) { cur_element = 0 }
list.active_element = cast(T)cur_element
if list.tween != nil {
tween_cancel(list.tween)
}
list.tween = tween_to(
&list.active_marker.y,
f32(list.active_element) * list.line_size,
0.25,
ease.Ease.Quadratic_Out,
)
}
if rl.IsKeyPressed(rl.KeyboardKey.ENTER) || rl.IsKeyPressed(rl.KeyboardKey.SPACE) {
list.menu_pressed(list.state, list.active_element)
}
}
menu_list_draw :: proc(list: ^MenuList($T)) {
if list.background[3] != 0 {
size := menu_list_get_size(list)
rl.DrawRectangleV(list.position - {40, 40}, size + {80, 80}, list.background)
}
2024-10-05 20:44:32 +03:00
rl.DrawTextEx(Res.Fonts.UI, ">", list.position + list.active_marker + {-30, 0}, 48, 2, rl.WHITE)
2024-10-04 21:16:58 +03:00
for el, i in list.elements {
pos := list.position + {0, f32(i) * list.line_size}
text := el.text
if el.type == .BOOL {
param := transmute(^bool)el.param
value := param^
text = rl.TextFormat("%s: %s", el.text, BoolStrings[value])
}
rl.DrawTextEx(Res.Fonts.UI, text, pos, list.font_size, 2, rl.WHITE)
2024-10-04 21:16:58 +03:00
}
}
menu_list_get_size :: proc(list: ^MenuList($T)) -> vec2 {
size := vec2{}
for el, i in list.elements {
line_size := rl.MeasureTextEx(Res.Fonts.UI, el.text, list.font_size, 2)
2024-10-04 21:16:58 +03:00
if line_size.x > size.x {
size.x = line_size.x
}
size.y += list.line_size
}
return size
}