2024-10-04 21:16:58 +03:00
|
|
|
package main
|
|
|
|
|
|
|
|
import "core:fmt"
|
2024-11-04 17:28:34 +03:00
|
|
|
import "core:math/ease"
|
|
|
|
import "ntween"
|
|
|
|
import rl "vendor:raylib"
|
2024-10-04 21:16:58 +03:00
|
|
|
|
2024-10-06 10:59:07 +03:00
|
|
|
MenuItemType :: enum {
|
|
|
|
NONE,
|
|
|
|
BOOL,
|
|
|
|
INT,
|
|
|
|
}
|
|
|
|
|
|
|
|
BoolStrings := map[bool]cstring {
|
2024-11-04 17:28:34 +03:00
|
|
|
true = "вкл",
|
|
|
|
false = "выкл",
|
2024-10-06 10:59:07 +03:00
|
|
|
}
|
|
|
|
|
2024-11-04 17:28:34 +03:00
|
|
|
MenuItem :: struct {
|
|
|
|
text: cstring,
|
2024-10-06 10:59:07 +03:00
|
|
|
param: rawptr,
|
2024-11-04 17:28:34 +03:00
|
|
|
type: MenuItemType,
|
2024-10-06 10:59:07 +03:00
|
|
|
}
|
|
|
|
|
2024-10-04 21:16:58 +03:00
|
|
|
MenuList :: struct($T: typeid) {
|
2024-11-04 17:28:34 +03:00
|
|
|
state: ^GameState,
|
|
|
|
position: vec2,
|
|
|
|
line_size: f32,
|
|
|
|
font_size: f32,
|
2024-10-04 21:16:58 +03:00
|
|
|
active_element: T,
|
2024-11-04 17:28:34 +03:00
|
|
|
active_marker: vec2,
|
|
|
|
tween: ^ntween.Tween(f32),
|
|
|
|
elements: ^[T]MenuItem,
|
|
|
|
menu_pressed: proc(state: ^GameState, element: T),
|
|
|
|
background: rl.Color,
|
|
|
|
mouse_pos: vec2,
|
2024-10-04 21:16:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
2024-11-04 17:28:34 +03:00
|
|
|
if rl.CheckCollisionPointRec(
|
|
|
|
list.mouse_pos,
|
|
|
|
rl.Rectangle{x = list.position.x, y = list.position.y, width = size.x, height = size.y},
|
|
|
|
) {
|
2024-10-04 21:16:58 +03:00
|
|
|
if last_mouse_pos != list.mouse_pos {
|
2024-11-04 17:28:34 +03:00
|
|
|
mouse_relative := list.mouse_pos - list.position
|
2024-10-04 21:16:58 +03:00
|
|
|
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 {
|
2024-11-04 17:28:34 +03:00
|
|
|
if cur_element < 0 {cur_element = len(T) - 1}
|
|
|
|
if cur_element == len(T) {cur_element = 0}
|
2024-10-04 21:16:58 +03:00
|
|
|
list.active_element = cast(T)cur_element
|
|
|
|
if list.tween != nil {
|
2024-11-04 17:28:34 +03:00
|
|
|
ntween.cancel(list.tween)
|
2024-10-04 21:16:58 +03:00
|
|
|
}
|
2024-11-04 17:28:34 +03:00
|
|
|
list.tween = ntween.animate(
|
|
|
|
&f32_tweens,
|
2024-10-04 21:16:58 +03:00
|
|
|
&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-11-04 17:28:34 +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}
|
2024-11-04 17:28:34 +03:00
|
|
|
text := el.text
|
2024-10-06 10:59:07 +03:00
|
|
|
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 {
|
2024-10-06 10:59:07 +03:00
|
|
|
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
|
|
|
|
}
|