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
|
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 {
|
Program :: struct {
|
||||||
ui_state: UiState,
|
ui_state: UiContext,
|
||||||
matrix_field_pool: FieldPool(f32),
|
matrix_field_pool: FieldPool(f32),
|
||||||
matrix_mode: MatrixType,
|
matrix_mode_perceived: MatrixType,
|
||||||
|
matrix_mode_actual: MatrixType,
|
||||||
grid: Grid,
|
grid: Grid,
|
||||||
font_style: FontStyle,
|
font_style: FontStyle,
|
||||||
|
state: ProgramState,
|
||||||
|
message_type: ProgramMessageType,
|
||||||
}
|
}
|
||||||
|
|
||||||
Grid :: struct {
|
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)
|
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) {
|
field_pool_init :: proc(pool: ^FieldPool($T), capacity: int, allocator := context.allocator) {
|
||||||
fixed_pool.init(&pool.values, capacity, allocator)
|
fixed_pool.init(&pool.values, capacity, allocator)
|
||||||
fixed_pool.init(&pool.inputs, 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)
|
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 {
|
matrix_add_button_callback_data := UiButton_AddMat2CallbackData {
|
||||||
program = &program,
|
program = &program,
|
||||||
mat = mat2{0, 1, 2, 3},
|
mat = mat2{0, 1, 2, 3},
|
||||||
|
|
@ -210,8 +241,12 @@ update :: proc() {
|
||||||
ui_button(ui_button_size_top_bar, {label = "#12#"})
|
ui_button(ui_button_size_top_bar, {label = "#12#"})
|
||||||
ui_same_line()
|
ui_same_line()
|
||||||
matrix_options := enum_to_raygui_options_string(MatrixType, context.temp_allocator)
|
matrix_options := enum_to_raygui_options_string(MatrixType, context.temp_allocator)
|
||||||
matrix_mode_ref := cast(^i32)&program.matrix_mode
|
matrix_mode_ref := cast(^i32)&program.matrix_mode_perceived
|
||||||
ui_dropdown(ui_dropdown_size_top_bar, {label = matrix_options, active = matrix_mode_ref})
|
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_end()
|
||||||
ui_container_begin({label = "Matrices"})
|
ui_container_begin({label = "Matrices"})
|
||||||
field_pool := &program.matrix_field_pool
|
field_pool := &program.matrix_field_pool
|
||||||
|
|
@ -227,12 +262,10 @@ update :: proc() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui_container_end()
|
ui_container_end()
|
||||||
ui_elements := ui_end()
|
return ui_end()
|
||||||
|
}
|
||||||
rl.BeginDrawing()
|
|
||||||
defer rl.EndDrawing()
|
|
||||||
rl.ClearBackground(rl.BLACK)
|
|
||||||
|
|
||||||
|
program_render_ui :: proc(ui_elements: []UiElement) {
|
||||||
for element in ui_elements {
|
for element in ui_elements {
|
||||||
switch element.type {
|
switch element.type {
|
||||||
case .Button:
|
case .Button:
|
||||||
|
|
@ -259,17 +292,59 @@ update :: proc() {
|
||||||
style := program.ui_state.style
|
style := program.ui_state.style
|
||||||
draw_text(data.text, rect_get_tl(element.area), style.font_style, data.color)
|
draw_text(data.text, rect_get_tl(element.area), style.font_style, data.color)
|
||||||
case .DropDown:
|
case .DropDown:
|
||||||
data := element.data.(UiElementData_DropDown)
|
data := element.data.(UiElementData_Dropdown)
|
||||||
edit_mode := ui_element_is_editing(program.ui_state, element.id)
|
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 rl.GuiDropdownBox(element.area, data.label, data.active, edit_mode) {
|
||||||
if edit_mode {
|
if edit_mode {
|
||||||
ui_element_focus_reset(&program.ui_state)
|
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 {
|
} else {
|
||||||
ui_element_focus(&program.ui_state, element.id)
|
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)
|
free_all(context.temp_allocator)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
28
ui.odin
28
ui.odin
|
|
@ -5,7 +5,7 @@ import "core:fmt"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import rl "libraries/raylib"
|
import rl "libraries/raylib"
|
||||||
|
|
||||||
@(private="file") state_current: ^UiState
|
@(private="file") state_current: ^UiContext
|
||||||
|
|
||||||
UiElementType :: enum {
|
UiElementType :: enum {
|
||||||
Input,
|
Input,
|
||||||
|
|
@ -20,7 +20,7 @@ UiElementData :: union {
|
||||||
UiElementData_Input,
|
UiElementData_Input,
|
||||||
UiElementData_Container,
|
UiElementData_Container,
|
||||||
UiElementData_Text,
|
UiElementData_Text,
|
||||||
UiElementData_DropDown,
|
UiElementData_Dropdown,
|
||||||
}
|
}
|
||||||
|
|
||||||
UiElement :: struct {
|
UiElement :: struct {
|
||||||
|
|
@ -35,7 +35,7 @@ UiElementId :: bit_field u32 {
|
||||||
element_index: u16 | 16,
|
element_index: u16 | 16,
|
||||||
}
|
}
|
||||||
|
|
||||||
UiState :: struct {
|
UiContext :: struct {
|
||||||
origin, position_left, position: v2,
|
origin, position_left, position: v2,
|
||||||
same_line: bool,
|
same_line: bool,
|
||||||
style: UiStyle,
|
style: UiStyle,
|
||||||
|
|
@ -51,7 +51,7 @@ UiStyle :: struct {
|
||||||
font_style: FontStyle,
|
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^ = {
|
state^ = {
|
||||||
element_focus_id = ui_id_invalid(),
|
element_focus_id = ui_id_invalid(),
|
||||||
origin = origin,
|
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
|
state_current = state
|
||||||
clear(&state.elements)
|
clear(&state.elements)
|
||||||
state.id_current = {group_index = 0, element_index = 0}
|
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})
|
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,
|
label: cstring,
|
||||||
active: ^i32,
|
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
|
state := state_current
|
||||||
area := _ui_advance_element(state, size)
|
area := _ui_advance_element(state, size)
|
||||||
state.id_current.element_index += 1
|
state.id_current.element_index += 1
|
||||||
|
|
@ -221,15 +225,15 @@ ui_same_line :: proc() {
|
||||||
state_current.same_line = true
|
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
|
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
|
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()
|
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)}
|
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.group_element_count > 0 {
|
||||||
if state.same_line {
|
if state.same_line {
|
||||||
previous_element := state.elements[len(state.elements) - 1]
|
previous_element := state.elements[len(state.elements) - 1]
|
||||||
|
|
@ -262,7 +266,7 @@ _ui_advance_element :: proc(state: ^UiState, size: v2) -> rect2 {
|
||||||
return area
|
return area
|
||||||
}
|
}
|
||||||
|
|
||||||
_ui_advance_container :: proc(state: ^UiState) -> rect2 {
|
_ui_advance_container :: proc(state: ^UiContext) -> rect2 {
|
||||||
state.position += state.style.margin
|
state.position += state.style.margin
|
||||||
return {**state.position, 0.0, 0.0}
|
return {**state.position, 0.0, 0.0}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue