Dropdown box
This commit is contained in:
parent
af44a9c367
commit
4e9fe28e4d
2 changed files with 102 additions and 23 deletions
97
program.odin
97
program.odin
|
|
@ -20,12 +20,28 @@ FontStyle :: struct {
|
|||
size, spacing: f32
|
||||
}
|
||||
|
||||
ProgramState :: enum {
|
||||
Normal,
|
||||
Message,
|
||||
}
|
||||
|
||||
ProgramMessageType :: enum {
|
||||
ChangeMatrixTypeClearData,
|
||||
}
|
||||
|
||||
@rodata program_messages := [ProgramMessageType]cstring {
|
||||
.ChangeMatrixTypeClearData = "Changing the matrix type will delete all current matrices.\nAre you sure you want to do this?",
|
||||
}
|
||||
|
||||
Program :: struct {
|
||||
ui_state: UiState,
|
||||
ui_state: UiContext,
|
||||
matrix_field_pool: FieldPool(f32),
|
||||
matrix_mode: MatrixType,
|
||||
matrix_mode_perceived: MatrixType,
|
||||
matrix_mode_actual: MatrixType,
|
||||
grid: Grid,
|
||||
font_style: FontStyle,
|
||||
state: ProgramState,
|
||||
message_type: ProgramMessageType,
|
||||
}
|
||||
|
||||
Grid :: struct {
|
||||
|
|
@ -45,6 +61,11 @@ field_pool_get :: proc(pool: ^FieldPool($T), count: int) -> (values: []T, inputs
|
|||
return fixed_pool.get(&pool.values, count), fixed_pool.get(&pool.inputs, count)
|
||||
}
|
||||
|
||||
field_pool_clear :: proc(pool: ^FieldPool($T)) {
|
||||
fixed_pool.clear(&pool.values)
|
||||
fixed_pool.clear(&pool.inputs)
|
||||
}
|
||||
|
||||
field_pool_init :: proc(pool: ^FieldPool($T), capacity: int, allocator := context.allocator) {
|
||||
fixed_pool.init(&pool.values, capacity, allocator)
|
||||
fixed_pool.init(&pool.inputs, capacity, allocator)
|
||||
|
|
@ -193,7 +214,17 @@ init :: proc() {
|
|||
ui_init(&program.ui_state, ui_style, {0, 0}, context.temp_allocator)
|
||||
}
|
||||
|
||||
update :: proc() {
|
||||
program_set_message_state :: proc(program: ^Program, message: ProgramMessageType) {
|
||||
program.state = .Message
|
||||
program.message_type = message
|
||||
}
|
||||
|
||||
program_matrix_mode_dropdown_callback :: proc(previous, current: i32, data: rawptr) {
|
||||
program := cast(^Program)data
|
||||
program_set_message_state(program, .ChangeMatrixTypeClearData)
|
||||
}
|
||||
|
||||
program_build_ui :: proc() -> []UiElement {
|
||||
matrix_add_button_callback_data := UiButton_AddMat2CallbackData {
|
||||
program = &program,
|
||||
mat = mat2{0, 1, 2, 3},
|
||||
|
|
@ -210,8 +241,12 @@ update :: proc() {
|
|||
ui_button(ui_button_size_top_bar, {label = "#12#"})
|
||||
ui_same_line()
|
||||
matrix_options := enum_to_raygui_options_string(MatrixType, context.temp_allocator)
|
||||
matrix_mode_ref := cast(^i32)&program.matrix_mode
|
||||
ui_dropdown(ui_dropdown_size_top_bar, {label = matrix_options, active = matrix_mode_ref})
|
||||
matrix_mode_ref := cast(^i32)&program.matrix_mode_perceived
|
||||
ui_dropdown(ui_dropdown_size_top_bar, {
|
||||
label = matrix_options,
|
||||
active = matrix_mode_ref,
|
||||
callback = program_matrix_mode_dropdown_callback,
|
||||
callback_data = cast(rawptr)&program})
|
||||
ui_container_end()
|
||||
ui_container_begin({label = "Matrices"})
|
||||
field_pool := &program.matrix_field_pool
|
||||
|
|
@ -227,12 +262,10 @@ update :: proc() {
|
|||
}
|
||||
}
|
||||
ui_container_end()
|
||||
ui_elements := ui_end()
|
||||
|
||||
rl.BeginDrawing()
|
||||
defer rl.EndDrawing()
|
||||
rl.ClearBackground(rl.BLACK)
|
||||
return ui_end()
|
||||
}
|
||||
|
||||
program_render_ui :: proc(ui_elements: []UiElement) {
|
||||
for element in ui_elements {
|
||||
switch element.type {
|
||||
case .Button:
|
||||
|
|
@ -259,17 +292,59 @@ update :: proc() {
|
|||
style := program.ui_state.style
|
||||
draw_text(data.text, rect_get_tl(element.area), style.font_style, data.color)
|
||||
case .DropDown:
|
||||
data := element.data.(UiElementData_DropDown)
|
||||
data := element.data.(UiElementData_Dropdown)
|
||||
edit_mode := ui_element_is_editing(program.ui_state, element.id)
|
||||
active_previous := data.active^
|
||||
if rl.GuiDropdownBox(element.area, data.label, data.active, edit_mode) {
|
||||
if edit_mode {
|
||||
ui_element_focus_reset(&program.ui_state)
|
||||
if active_previous != data.active^ && data.callback != nil {
|
||||
data.callback(active_previous, data.active^, data.callback_data)
|
||||
}
|
||||
} else {
|
||||
ui_element_focus(&program.ui_state, element.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update :: proc() {
|
||||
ui_elements := program_build_ui()
|
||||
|
||||
rl.BeginDrawing()
|
||||
defer rl.EndDrawing()
|
||||
rl.ClearBackground(rl.BLACK)
|
||||
|
||||
if program.state != .Normal {
|
||||
rl.GuiDisable()
|
||||
}
|
||||
program_render_ui(ui_elements)
|
||||
if program.state != .Normal {
|
||||
rl.GuiEnable()
|
||||
}
|
||||
|
||||
switch program.state {
|
||||
case .Normal:
|
||||
case .Message:
|
||||
switch program.message_type {
|
||||
case .ChangeMatrixTypeClearData:
|
||||
size := v2{224.0, 128.0}
|
||||
position := v2(iv2{rl.GetRenderWidth(), rl.GetRenderHeight()} / 2.0) - size / 2.0
|
||||
area := rect2{**position, **size}
|
||||
action := rl.GuiMessageBox(area, "Message", program_messages[program.message_type], "Confirm;Cancel")
|
||||
switch action {
|
||||
case 0:
|
||||
case 1:
|
||||
field_pool_clear(&program.matrix_field_pool)
|
||||
program.matrix_mode_actual = program.matrix_mode_perceived
|
||||
program.state = .Normal
|
||||
case 2:
|
||||
program.matrix_mode_perceived = program.matrix_mode_actual
|
||||
program.state = .Normal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_all(context.temp_allocator)
|
||||
}
|
||||
|
|
|
|||
28
ui.odin
28
ui.odin
|
|
@ -5,7 +5,7 @@ import "core:fmt"
|
|||
import "core:mem"
|
||||
import rl "libraries/raylib"
|
||||
|
||||
@(private="file") state_current: ^UiState
|
||||
@(private="file") state_current: ^UiContext
|
||||
|
||||
UiElementType :: enum {
|
||||
Input,
|
||||
|
|
@ -20,7 +20,7 @@ UiElementData :: union {
|
|||
UiElementData_Input,
|
||||
UiElementData_Container,
|
||||
UiElementData_Text,
|
||||
UiElementData_DropDown,
|
||||
UiElementData_Dropdown,
|
||||
}
|
||||
|
||||
UiElement :: struct {
|
||||
|
|
@ -35,7 +35,7 @@ UiElementId :: bit_field u32 {
|
|||
element_index: u16 | 16,
|
||||
}
|
||||
|
||||
UiState :: struct {
|
||||
UiContext :: struct {
|
||||
origin, position_left, position: v2,
|
||||
same_line: bool,
|
||||
style: UiStyle,
|
||||
|
|
@ -51,7 +51,7 @@ UiStyle :: struct {
|
|||
font_style: FontStyle,
|
||||
}
|
||||
|
||||
ui_init :: proc(state: ^UiState, style: UiStyle, origin: v2, allocator: mem.Allocator) {
|
||||
ui_init :: proc(state: ^UiContext, style: UiStyle, origin: v2, allocator: mem.Allocator) {
|
||||
state^ = {
|
||||
element_focus_id = ui_id_invalid(),
|
||||
origin = origin,
|
||||
|
|
@ -61,7 +61,7 @@ ui_init :: proc(state: ^UiState, style: UiStyle, origin: v2, allocator: mem.Allo
|
|||
}
|
||||
}
|
||||
|
||||
ui_start :: proc(state: ^UiState) {
|
||||
ui_start :: proc(state: ^UiContext) {
|
||||
state_current = state
|
||||
clear(&state.elements)
|
||||
state.id_current = {group_index = 0, element_index = 0}
|
||||
|
|
@ -205,12 +205,16 @@ ui_mat4 :: proc(input_field_size: v2, inputs: [][]byte, min, max: f32) {
|
|||
ui_input(input_field_size, {label = "", input = inputs[15], min = min, max = max})
|
||||
}
|
||||
|
||||
UiElementData_DropDown :: struct {
|
||||
UiElementCallback_Dropdown :: proc(previous, current: i32, data: rawptr)
|
||||
|
||||
UiElementData_Dropdown :: struct {
|
||||
label: cstring,
|
||||
active: ^i32,
|
||||
callback: UiElementCallback_Dropdown,
|
||||
callback_data: rawptr,
|
||||
}
|
||||
|
||||
ui_dropdown :: proc(size: v2, data: UiElementData_DropDown) {
|
||||
ui_dropdown :: proc(size: v2, data: UiElementData_Dropdown) {
|
||||
state := state_current
|
||||
area := _ui_advance_element(state, size)
|
||||
state.id_current.element_index += 1
|
||||
|
|
@ -221,15 +225,15 @@ ui_same_line :: proc() {
|
|||
state_current.same_line = true
|
||||
}
|
||||
|
||||
ui_element_is_editing :: proc(state: UiState, id: UiElementId) -> bool {
|
||||
ui_element_is_editing :: proc(state: UiContext, id: UiElementId) -> bool {
|
||||
return state.element_focus_id == id
|
||||
}
|
||||
|
||||
ui_element_focus :: proc(state: ^UiState, id: UiElementId) {
|
||||
ui_element_focus :: proc(state: ^UiContext, id: UiElementId) {
|
||||
state.element_focus_id = id
|
||||
}
|
||||
|
||||
ui_element_focus_reset :: proc(state: ^UiState) {
|
||||
ui_element_focus_reset :: proc(state: ^UiContext) {
|
||||
state.element_focus_id = ui_id_invalid()
|
||||
}
|
||||
|
||||
|
|
@ -237,7 +241,7 @@ ui_id_invalid :: proc() -> UiElementId {
|
|||
return {group_index = max(u16), element_index = max(u16)}
|
||||
}
|
||||
|
||||
_ui_advance_element :: proc(state: ^UiState, size: v2) -> rect2 {
|
||||
_ui_advance_element :: proc(state: ^UiContext, size: v2) -> rect2 {
|
||||
if state.group_element_count > 0 {
|
||||
if state.same_line {
|
||||
previous_element := state.elements[len(state.elements) - 1]
|
||||
|
|
@ -262,7 +266,7 @@ _ui_advance_element :: proc(state: ^UiState, size: v2) -> rect2 {
|
|||
return area
|
||||
}
|
||||
|
||||
_ui_advance_container :: proc(state: ^UiState) -> rect2 {
|
||||
_ui_advance_container :: proc(state: ^UiContext) -> rect2 {
|
||||
state.position += state.style.margin
|
||||
return {**state.position, 0.0, 0.0}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue