WIP: Stuff related to working on the settings menu + more
Moved core ui to its own folder. Worked on theming (proper light and dark theme) Began to work on the scroll box widget and input box constructions I added back a script for flattening the codebase: gen_flattened_codebase.ps1
This commit is contained in:
parent
ddff1fcae6
commit
b137bc542c
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,4 +4,4 @@ build/**
|
||||
logs
|
||||
.ark
|
||||
logs*.zip
|
||||
code_compiler_staged
|
||||
code_flattened
|
||||
|
@ -52,12 +52,13 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if true && ! loaded
|
||||
if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
flags = {},
|
||||
anchor = range2({},{}),
|
||||
alignment = {0.5, 0.5},
|
||||
// alignment = UI_Align_Presets.text_centered,
|
||||
text_alignment = {0.0, 1.5},
|
||||
font_size = 12,
|
||||
margins = {0, 0, 0, 0},
|
||||
@ -67,34 +68,30 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f
|
||||
size = range2({},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = Color_ThmDark_BG,
|
||||
border_color = Color_ThmDark_Border_Default,
|
||||
bg_color = app_color.bg,
|
||||
border_color = app_color.border_default,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = Color_ThmDark_Text_Default,
|
||||
text_color = app_color.text_default,
|
||||
cursor = {},
|
||||
}
|
||||
|
||||
// loaded = true
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
{
|
||||
Hot: {
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
bg_color = Color_ThmDark_Btn_BG_Hot
|
||||
text_color = Color_ThmDark_Text_Hot
|
||||
bg_color = app_color.btn_bg_hot
|
||||
text_color = app_color.text_hot
|
||||
}
|
||||
{
|
||||
Active: {
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
bg_color = Color_ThmDark_Btn_BG_Active
|
||||
text_color = Color_ThmDark_Text_Active
|
||||
}
|
||||
|
||||
theme = UI_Theme {
|
||||
layout_combo, style_combo
|
||||
bg_color = app_color.btn_bg_active
|
||||
text_color = app_color.text_active
|
||||
}
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
@ -105,7 +102,8 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f
|
||||
{
|
||||
using screen_ui.menu_bar
|
||||
ui_theme_app_menu_bar_default()
|
||||
container = ui_hbox( .Left_To_Right, "Menu Bar" )
|
||||
container = ui_hbox_begin( .Left_To_Right, "Menu Bar" )
|
||||
ui_parent(container)
|
||||
{
|
||||
using container
|
||||
layout.flags = {.Fixed_Position_X, .Fixed_Position_Y, .Fixed_Width, .Fixed_Height, .Origin_At_Anchor_Center}
|
||||
@ -114,7 +112,7 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f
|
||||
text = str_intern("menu_bar")
|
||||
}
|
||||
|
||||
ui_theme_btn_default()
|
||||
ui_theme_btn()
|
||||
move_box := ui_button("Move Box");
|
||||
{
|
||||
using move_box
|
||||
@ -122,7 +120,7 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f
|
||||
pos += input.mouse.delta
|
||||
should_raise = true
|
||||
}
|
||||
layout.anchor.ratio.x = 0.4
|
||||
layout.anchor.ratio.x = 1.0
|
||||
}
|
||||
|
||||
spacer := ui_spacer("Menu Bar: Move Spacer")
|
||||
@ -135,17 +133,18 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f
|
||||
using settings_btn
|
||||
text = str_intern("Settings")
|
||||
layout.flags = {
|
||||
// .Scale_Width_By_Height_Ratio,
|
||||
.Fixed_Width
|
||||
.Scale_Width_By_Height_Ratio,
|
||||
// .Fixed_Width
|
||||
}
|
||||
layout.size.min.x = 100
|
||||
layout.size.ratio.x = 2.0
|
||||
if pressed {
|
||||
screen_ui.settings_menu.is_open = true
|
||||
}
|
||||
}
|
||||
|
||||
spacer = ui_spacer("Menu Bar: End Spacer")
|
||||
spacer.layout.anchor.ratio.x = 1.0
|
||||
spacer.layout.anchor.ratio.x = 2.0
|
||||
|
||||
ui_hbox_end(container, compute_layout = false)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -156,22 +155,18 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b
|
||||
using state := get_state()
|
||||
using state.screen_ui
|
||||
if ! settings_menu.is_open do return
|
||||
app_color := app_color_theme()
|
||||
|
||||
using settings_menu
|
||||
if size.x < min_size.x do size.x = min_size.x
|
||||
if size.y < min_size.y do size.y = min_size.y
|
||||
|
||||
ui_theme_transparent()
|
||||
container = ui_widget("Settings Menu", {})
|
||||
{
|
||||
ui_theme_window_panel()
|
||||
container = ui_widget("Settings Menu", {}); {
|
||||
using container
|
||||
layout.flags = { .Fixed_Width, .Fixed_Height, .Fixed_Position_X, .Fixed_Position_Y, .Origin_At_Anchor_Center }
|
||||
style.bg_color = Color_ThmDark_Translucent_Panel
|
||||
style.border_color = { 0, 0, 0, 200 }
|
||||
layout.alignment = {0.0, 0.0}
|
||||
layout.border_width = 1.0
|
||||
layout.pos = pos
|
||||
layout.size = range2( size, {})
|
||||
layout.flags = { .Fixed_Width, .Fixed_Height, .Fixed_Position_X, .Fixed_Position_Y, .Origin_At_Anchor_Center }
|
||||
layout.pos = pos
|
||||
layout.size = range2( size, {})
|
||||
}
|
||||
ui_parent(container)
|
||||
if settings_menu.is_maximized {
|
||||
@ -179,54 +174,27 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b
|
||||
layout.flags = {.Origin_At_Anchor_Center }
|
||||
layout.pos = {}
|
||||
}
|
||||
should_raise |= ui_resizable_handles( & container, & pos, & size/*, compute_layout = true*/)
|
||||
// ui_box_compute_layout(container)
|
||||
should_raise |= ui_resizable_handles( & container, & pos, & size)
|
||||
|
||||
vbox := ui_vbox_begin( .Top_To_Bottom, "Settings Menu: VBox", {.Mouse_Clickable}, compute_layout = true)
|
||||
{
|
||||
should_raise |= b32(vbox.active)
|
||||
ui_parent(vbox)
|
||||
|
||||
ui_layout( UI_Layout {
|
||||
// font_size = 16,
|
||||
// alignment = {0, 1},
|
||||
})
|
||||
ui_style( UI_Style {
|
||||
// bg_color = Color_Transparent,
|
||||
font = default_font,
|
||||
text_color = Color_White,
|
||||
})
|
||||
ui_style_ref().hot.bg_color = Color_Blue
|
||||
frame_bar := ui_hbox_begin(.Left_To_Right, "Settings Menu: Frame Bar", { .Mouse_Clickable, .Focusable, .Click_To_Focus })
|
||||
ui_theme_window_bar()
|
||||
frame_bar := ui_hbox_begin(.Left_To_Right, "Settings Menu: Frame Bar", { .Mouse_Clickable })
|
||||
{
|
||||
frame_bar.layout.flags = {.Fixed_Height}
|
||||
frame_bar.layout.size.min.y = 50
|
||||
ui_parent(frame_bar)
|
||||
|
||||
ui_layout( UI_Layout {
|
||||
font_size = 18,
|
||||
})
|
||||
title := ui_text("Settings Menu: Title", str_intern("Settings Menu"), {.Disabled})
|
||||
{
|
||||
ui_theme_text()
|
||||
title := ui_text("Settings Menu: Title", str_intern("Settings Menu"), {.Disabled}); {
|
||||
using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins = { 0, 0, 15, 0}
|
||||
layout.text_alignment = {0 , 0.5}
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.font_size = 16
|
||||
}
|
||||
|
||||
ui_layout( UI_Layout {
|
||||
font_size = 16,
|
||||
})
|
||||
|
||||
ui_style(ui_style_peek())
|
||||
style := ui_style_ref()
|
||||
maximize_btn := ui_button("Settings Menu: Maximize Btn")
|
||||
{
|
||||
ui_theme_window_bar_btn()
|
||||
maximize_btn := ui_button("Settings Menu: Maximize Btn"); {
|
||||
using maximize_btn
|
||||
layout.flags = {.Fixed_Width}
|
||||
layout.size.min = {50, 50}
|
||||
layout.text_alignment = {0.5, 0.5}
|
||||
layout.anchor.ratio.x = 1.0
|
||||
if maximize_btn.pressed {
|
||||
settings_menu.is_maximized = ~settings_menu.is_maximized
|
||||
should_raise = true
|
||||
@ -234,19 +202,12 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b
|
||||
if settings_menu.is_maximized do text = str_intern("min")
|
||||
else do text = str_intern("max")
|
||||
}
|
||||
close_btn := ui_button("Settings Menu: Close Btn")
|
||||
{
|
||||
close_btn := ui_button("Settings Menu: Close Btn"); {
|
||||
using close_btn
|
||||
text = str_intern("close")
|
||||
layout.flags = {.Fixed_Width}
|
||||
layout.size.min = {50, 0}
|
||||
layout.text_alignment = {0.5, 0.5}
|
||||
layout.anchor.ratio.x = 1.0
|
||||
if close_btn.pressed {
|
||||
settings_menu.is_open = false
|
||||
}
|
||||
if close_btn.hot do style.bg_color = app_color.window_btn_close_bg_hot
|
||||
if close_btn.pressed do settings_menu.is_open = false
|
||||
}
|
||||
|
||||
ui_hbox_end(frame_bar, compute_layout = true)
|
||||
}
|
||||
if frame_bar.active {
|
||||
@ -254,66 +215,109 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b
|
||||
should_raise = true
|
||||
}
|
||||
|
||||
// Populate settings with values from config (hardcoded for now)
|
||||
ui_layout(UI_Layout {
|
||||
flags = {
|
||||
// .Origin_At_Anchor_Center,
|
||||
// .Fixed_Height,
|
||||
},
|
||||
// pos = {0, 50},
|
||||
// size = range2({100, 100},{}),
|
||||
// alignment = {0,0},
|
||||
})
|
||||
ui_style( UI_Style {
|
||||
// bg_color = Color_GreyRed
|
||||
})
|
||||
drop_down_bar := ui_hbox_begin(.Left_To_Right, "settings_menu.vbox: config drop_down_bar", {.Mouse_Clickable})
|
||||
btn : UI_Widget
|
||||
@static config_drop_down_open := false
|
||||
ui_theme_drop_down()
|
||||
drop_down_bar := ui_hbox_begin(.Left_To_Right, "settings_menu.vbox: config drop_down_bar", {.Mouse_Clickable })
|
||||
{
|
||||
drop_down_bar.layout.anchor.ratio.y = 0.1
|
||||
ui_parent_push(drop_down_bar)
|
||||
{
|
||||
using drop_down_bar
|
||||
text = str_intern("drop_down_bar")
|
||||
// style.bg_color = { 55, 55, 55, 100 }
|
||||
style.font = default_font
|
||||
style.text_color = Color_White
|
||||
layout.flags = {.Fixed_Height}
|
||||
layout.font_size = 12
|
||||
layout.text_alignment = {1, 0}
|
||||
layout.size.min.y = 35
|
||||
layout.anchor.ratio.y = 1.0
|
||||
}
|
||||
ui_parent(drop_down_bar)
|
||||
|
||||
btn = ui_text("pls", str_intern("Lets figure this out..."))
|
||||
{
|
||||
using btn
|
||||
text = str_intern("Config")
|
||||
style.font = default_font
|
||||
style.text_color = Color_White
|
||||
// layout.flags = {.Origin_At_Anchor_Center}
|
||||
ui_theme_text()
|
||||
title := ui_text("drop_down_bar.btn", str_intern("drop_down_bar.btn")); {
|
||||
using title
|
||||
text = str_intern("App Config")
|
||||
style.text_color = drop_down_bar.style.text_color
|
||||
layout.alignment = {0.0, 0.0}
|
||||
layout.text_alignment = {0.0, 0.5}
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.font_size = 12
|
||||
layout.margins = {0,0, 15, 0}
|
||||
layout.size.min.y = 35
|
||||
}
|
||||
um := ui_spacer("um...")
|
||||
um.layout.anchor.ratio.x = 1.0
|
||||
ui_parent_pop()
|
||||
ui_hbox_end(drop_down_bar, compute_layout = true)
|
||||
if drop_down_bar.pressed do config_drop_down_open = !config_drop_down_open
|
||||
}
|
||||
|
||||
// ui_layout(UI_Layout {
|
||||
if config_drop_down_open
|
||||
{
|
||||
{
|
||||
ui_theme_table_row(is_even = false)
|
||||
hb := ui_hbox(.Left_To_Right, "settings_menu.engine_refresh_hz.hb"); { using hb
|
||||
layout.size.min = {0, 30}
|
||||
layout.flags = {.Fixed_Height}
|
||||
layout.padding = to_ui_layout_side(4)
|
||||
}
|
||||
ui_theme_text(); title := ui_text("settings_menu.engine_refresh_hz.title", str_intern("Engine Refresh Hz")); { using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins.left = 10
|
||||
layout.text_alignment = {0, 0.5}
|
||||
|
||||
// })
|
||||
// ui_style( UI_Style {
|
||||
}
|
||||
input_box := ui_widget("settings_menu.engine_refresh.input_box", {.Mouse_Clickable, .Focusable, .Click_To_Focus}); { using input_box
|
||||
layout.flags = {.Fixed_Width}
|
||||
layout.margins.left = 5
|
||||
layout.padding.right = 10
|
||||
layout.size.min.x = 80
|
||||
if input_box.active do style.bg_color = app_color.input_box_bg_active
|
||||
else if input_box.hot do style.bg_color = app_color.input_box_bg_hot
|
||||
else do style.bg_color = app_color.input_box_bg
|
||||
style.corner_radii[0] = 0.35
|
||||
}
|
||||
@static value_str : Array(rune)
|
||||
if value_str.data == nil {
|
||||
error : AllocatorError
|
||||
value_str, error = array_init_reserve(rune, persistent_slab_allocator(), Kilo)
|
||||
ensure(error != AllocatorError.None, "Failed to allocate array for value_str of input_box")
|
||||
array_append( & value_str, rune('_'))
|
||||
}
|
||||
if input_box.active {
|
||||
array_append( & value_str, input.keyboard_events.chars_pressed )
|
||||
array_clear( input.keyboard_events.chars_pressed )
|
||||
}
|
||||
else if input_box.was_active {
|
||||
|
||||
// })
|
||||
// res_width_hbox := ui_hbox_begin(.Left_To_Right, "settings_menu.vbox: config.resolution_width: hbox", {})
|
||||
// ui_parent(res_width_hbox)
|
||||
|
||||
spacer := ui_spacer("Settings Menu: Spacer")
|
||||
spacer.layout.anchor.ratio.y = 1.0
|
||||
}
|
||||
else {
|
||||
array_clear( value_str)
|
||||
array_append( & value_str, to_runes(str_fmt_alloc("%v", config.engine_refresh_hz)))
|
||||
}
|
||||
// input_box
|
||||
{
|
||||
ui_parent(input_box)
|
||||
value_txt := ui_text("settings_menu.engine_refresh.refresh_value", to_str_runes_pair(value_str))
|
||||
value_txt.layout.text_alignment = vec2(1, 0.5)
|
||||
}
|
||||
|
||||
spacer := ui_spacer("settings_menu.engine_refresh.end_spacer")
|
||||
spacer.layout.flags = {.Fixed_Width}
|
||||
spacer.layout.size.min.x = 10
|
||||
// input_text := ui_text("settings_menu.engine_refresh", str_fmt_alloc(value_str))
|
||||
}
|
||||
{
|
||||
ui_theme_table_row(is_even = true)
|
||||
hb := ui_hbox(.Left_To_Right, "settings_menu.cam_min_zoom.hb"); { using hb
|
||||
layout.size.min = {0, 30}
|
||||
layout.flags = {.Fixed_Height}
|
||||
}
|
||||
ui_theme_text(); title := ui_text("settings_menu.cam_min_zoom.title", str_intern("Camera: Min Zoom")); { using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins.left = 10
|
||||
}
|
||||
}
|
||||
{
|
||||
ui_theme_table_row(is_even = false)
|
||||
hb := ui_hbox(.Left_To_Right, "settings_menu.cam_max_zoom.hb"); { using hb
|
||||
layout.size.min = {0, 30}
|
||||
layout.flags = {.Fixed_Height}
|
||||
}
|
||||
ui_theme_text(); title := ui_text("settings_menu.cam_max_zoom.title", str_intern("Camera: Max Zoom")); { using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins.left = 10
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_vbox_end(vbox, compute_layout = false )
|
||||
}
|
||||
return
|
||||
|
@ -159,6 +159,8 @@ AppConfig :: struct {
|
||||
timing_fps_moving_avg_alpha : f32,
|
||||
|
||||
ui_resize_border_width : f32,
|
||||
|
||||
color_theme : AppColorTheme,
|
||||
}
|
||||
|
||||
AppWindow :: struct {
|
||||
@ -257,4 +259,7 @@ get_state :: #force_inline proc "contextless" () -> ^ State {
|
||||
// return get_state().frametime
|
||||
// }
|
||||
|
||||
app_config :: #force_inline proc "contextless" () -> AppConfig { return get_state().config }
|
||||
app_color_theme :: #force_inline proc "contextless" () -> AppColorTheme { return get_state().config.color_theme }
|
||||
|
||||
#endregion("State")
|
||||
|
473
code/sectr/app/ui_theme.odin
Normal file
473
code/sectr/app/ui_theme.odin
Normal file
@ -0,0 +1,473 @@
|
||||
package sectr
|
||||
|
||||
/*
|
||||
UI Themes: Comprise of UI_Box's layout & style
|
||||
|
||||
Provides presets for themes and their interface for manipulating the combo stacks in UI_State in pairs
|
||||
*/
|
||||
// TODO(Ed): Eventually this will have a configuration wizard, and we'll save the presets
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_btn :: proc()
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
flags = {},
|
||||
anchor = range2_zero,
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.5, 0.5},
|
||||
font_size = 16,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 1,
|
||||
pos = {0, 0},
|
||||
size = range2_zero,
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = app_color.btn_bg_default,
|
||||
border_color = app_color.border_default,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = app_color.text_default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
Hot: {
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
bg_color = app_color.btn_bg_hot
|
||||
text_color = app_color.text_hot
|
||||
}
|
||||
Active: {
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
bg_color = app_color.btn_bg_active
|
||||
text_color = app_color.text_active
|
||||
margins = {2, 2, 2, 2}
|
||||
}
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_drop_down :: proc()
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
flags = {.Fixed_Height},
|
||||
anchor = range2({0, 0},{}),
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.5, 0.5},
|
||||
font_size = 14,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 1,
|
||||
pos = {0, 0},
|
||||
size = range2({0,20},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = app_color.btn_bg_default,
|
||||
border_color = app_color.border_default,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = app_color.text_default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
Hot: {
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
bg_color = app_color.btn_bg_hot
|
||||
text_color = app_color.text_hot
|
||||
margins = {2, 2, 2, 2}
|
||||
}
|
||||
Active: {
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
bg_color = app_color.btn_bg_active
|
||||
text_color = app_color.text_active
|
||||
margins = {2, 2, 2, 2}
|
||||
}
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_table_row :: proc(is_even : bool)
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
// if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
table_bg : Color
|
||||
if is_even {
|
||||
table_bg = app_color.table_even_bg_color
|
||||
}
|
||||
else {
|
||||
table_bg = app_color.table_odd_bg_color
|
||||
}
|
||||
layout := UI_Layout {
|
||||
flags = {},
|
||||
anchor = range2({},{}),
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.0, 0.0},
|
||||
font_size = 16,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 0,
|
||||
pos = {0, 0},
|
||||
size = range2({},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = table_bg,
|
||||
border_color = Color_Transparent,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = app_color_theme().text_default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
Hot: {
|
||||
using layout_combo.disabled
|
||||
using style_combo.disabled
|
||||
}
|
||||
Active: {
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
}
|
||||
{
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
}
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_window_bar :: proc()
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded || true
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
flags = {.Fixed_Height},
|
||||
anchor = range2({},{}),
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.0, 0.0},
|
||||
font_size = 16,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 0.0,
|
||||
pos = {0, 0},
|
||||
size = range2({0, 35},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = app_color.window_bar_bg,
|
||||
border_color = Color_Transparent,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = app_color.text_default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
Disabled : {
|
||||
using layout_combo.disabled
|
||||
using style_combo.disabled
|
||||
}
|
||||
Hot: {
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
border_color = app_color.window_bar_border
|
||||
border_width = 1.0
|
||||
}
|
||||
Active: {
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
border_color = app_color.window_bar_border
|
||||
border_width = 2.0
|
||||
}
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_window_bar_title :: proc()
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
flags = {},
|
||||
anchor = range2({},{}),
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.0, 0.0},
|
||||
font_size = 16,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 0,
|
||||
pos = {0, 0},
|
||||
size = range2({},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = Color_Transparent,
|
||||
border_color = Color_Transparent,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = app_color.text_default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
Disabed: {
|
||||
using layout_combo.disabled
|
||||
using style_combo.disabled
|
||||
}
|
||||
Hot: {
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
}
|
||||
Active: {
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
}
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_window_bar_btn :: proc()
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
flags = {.Fixed_Width},
|
||||
anchor = range2({1, 0},{}),
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.5, 0.5},
|
||||
font_size = 16,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 1,
|
||||
pos = {0, 0},
|
||||
size = range2({50,0},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = app_color.btn_bg_default,
|
||||
border_color = app_color.border_default,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = app_color.text_default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
Hot: {
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
bg_color = app_color.btn_bg_hot
|
||||
text_color = app_color.text_hot
|
||||
}
|
||||
Active: {
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
bg_color = app_color.btn_bg_active
|
||||
text_color = app_color.text_active
|
||||
margins = {2, 2, 2, 2}
|
||||
}
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_window_panel :: proc()
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
flags = {},
|
||||
anchor = range2({},{}),
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.0, 0.0},
|
||||
font_size = 16,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 1,
|
||||
pos = {0, 0},
|
||||
size = range2({},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = app_color.window_panel_bg,
|
||||
border_color = app_color.window_panel_border,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = app_color.text_default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
Disabled: {
|
||||
using layout_combo.disabled
|
||||
using style_combo.disabled
|
||||
}
|
||||
Hot: {
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
}
|
||||
Active: {
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
}
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_transparent :: proc()
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
flags = {},
|
||||
anchor = range2({},{}),
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.0, 0.0},
|
||||
font_size = 16,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 0,
|
||||
pos = {0, 0},
|
||||
size = range2({},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = Color_Transparent,
|
||||
border_color = Color_Transparent,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = app_color.text_default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
{
|
||||
using layout_combo.disabled
|
||||
using style_combo.disabled
|
||||
}
|
||||
{
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
}
|
||||
{
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
}
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_text :: proc()
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
flags = {},
|
||||
anchor = range2({},{}),
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.0, 0.5},
|
||||
font_size = 14,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 0,
|
||||
pos = {0, 0},
|
||||
size = range2({},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = Color_Transparent,
|
||||
border_color = Color_Transparent,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = app_color.text_default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
{
|
||||
using layout_combo.disabled
|
||||
using style_combo.disabled
|
||||
}
|
||||
{
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
}
|
||||
{
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
}
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
package sectr
|
||||
|
||||
/*
|
||||
UI Themes: Comprise of UI_Box's layout & style
|
||||
|
||||
Provides presets for themes and their interface for manipulating the combo stacks in UI_State in pairs
|
||||
*/
|
||||
// TODO(Ed): Eventually this will have a configuration wizard, and we'll save the presets
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_btn_default :: proc()
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded
|
||||
{
|
||||
layout := UI_Layout {
|
||||
flags = {},
|
||||
anchor = range2({},{}),
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.5, 0.5},
|
||||
font_size = 16,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 1,
|
||||
pos = {0, 0},
|
||||
size = range2({},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = Color_ThmDark_Btn_BG_Default,
|
||||
border_color = Color_ThmDark_Border_Default,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = Color_ThmDark_Text_Default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
{
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
bg_color = Color_ThmDark_Btn_BG_Hot
|
||||
text_color = Color_ThmDark_Text_Hot
|
||||
margins = {2, 2, 2, 2}
|
||||
}
|
||||
{
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
bg_color = Color_ThmDark_Btn_BG_Active
|
||||
text_color = Color_ThmDark_Text_Active
|
||||
margins = {2, 2, 2, 2}
|
||||
}
|
||||
theme = UI_Theme {
|
||||
layout_combo, style_combo
|
||||
}
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_transparent :: proc()
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded || true
|
||||
{
|
||||
layout := UI_Layout {
|
||||
flags = {},
|
||||
anchor = range2({},{}),
|
||||
alignment = {0, 0},
|
||||
text_alignment = {0.0, 0.0},
|
||||
font_size = 16,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 0,
|
||||
pos = {0, 0},
|
||||
size = range2({},{})
|
||||
}
|
||||
style := UI_Style {
|
||||
bg_color = Color_Transparent,
|
||||
border_color = Color_Transparent,
|
||||
corner_radii = {},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = Color_ThmDark_Text_Default,
|
||||
cursor = {},
|
||||
}
|
||||
|
||||
layout_combo := to_ui_layout_combo(layout)
|
||||
style_combo := to_ui_style_combo(style)
|
||||
{
|
||||
using layout_combo.disabled
|
||||
using style_combo.disabled
|
||||
}
|
||||
{
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
}
|
||||
{
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
}
|
||||
|
||||
theme = UI_Theme {
|
||||
layout_combo, style_combo
|
||||
}
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
}
|
@ -31,32 +31,114 @@ Color_Debug_UI_Content_Bounds :: Color { 170, 120, 240, 160 }
|
||||
// TODO(Ed): The entire rendering pass should be post-processed by a tone curve configurable for the user
|
||||
// This is how you properly support any tonality of light or dark themes and not have it be base don the monitors raw output.
|
||||
|
||||
// Dark Theme
|
||||
AppColorTheme :: struct {
|
||||
light_limit,
|
||||
dark_limit,
|
||||
|
||||
// Brightest value limited to (text is the only exception):
|
||||
Color_ThmDark_BrightLimit :: Color {230, 230, 230, 255}
|
||||
// Darkness value limited to (text is the only exception):
|
||||
Color_ThmDark_DarkLimit :: Color {10, 10, 10, 255}
|
||||
bg,
|
||||
|
||||
border_default,
|
||||
|
||||
Color_ThmDark_BG :: Color {33, 33, 33, 255}
|
||||
btn_bg_default,
|
||||
btn_bg_hot,
|
||||
btn_bg_active,
|
||||
|
||||
Color_ThmDark_Translucent_Panel :: Color { 0, 0, 0, 60}
|
||||
input_box_bg,
|
||||
input_box_bg_hot,
|
||||
input_box_bg_active,
|
||||
|
||||
Color_ThmDark_ResizeHandle_Default :: Color_Transparent
|
||||
Color_ThmDark_ResizeHandle_Hot :: Color { 72, 72, 72, 90}
|
||||
Color_ThmDark_ResizeHandle_Active :: Color { 88, 88, 88, 90}
|
||||
resize_hndl_default,
|
||||
resize_hndl_hot,
|
||||
resize_hndl_active,
|
||||
|
||||
Color_ThmDark_Border_Default :: Color { 64, 64, 64, 255}
|
||||
table_even_bg_color,
|
||||
table_odd_bg_color,
|
||||
|
||||
Color_ThmDark_Btn_BG_Default :: Color { 40, 40, 40, 255}
|
||||
Color_ThmDark_Btn_BG_Hot :: Color { 60, 60, 70, 255}
|
||||
Color_ThmDark_Btn_BG_Active :: Color { 90, 100, 130, 255}
|
||||
text_default,
|
||||
text_hot,
|
||||
text_active,
|
||||
|
||||
Color_ThmDark_Text_Default :: Color {120, 117, 115, 255}
|
||||
Color_ThmDark_Text_Hot :: Color {180, 180, 180, 255}
|
||||
Color_ThmDark_Text_Active :: Color {240, 240, 240, 255}
|
||||
translucent_panel,
|
||||
|
||||
// Light Theme
|
||||
window_bar_border,
|
||||
window_bar_bg,
|
||||
window_btn_close_bg_hot,
|
||||
|
||||
// LightTheme_BG :: Color { 120, 120, 120, 255 }
|
||||
window_panel_bg,
|
||||
window_panel_border \
|
||||
: Color
|
||||
}
|
||||
|
||||
App_Thm_Dusk :: AppColorTheme {
|
||||
light_limit = Color {125, 125, 125, 255},
|
||||
dark_limit = Color { 10, 10, 10, 255},
|
||||
|
||||
bg = Color {33, 33, 33, 255},
|
||||
|
||||
border_default = Color { 64, 64, 64, 255},
|
||||
|
||||
btn_bg_default = Color { 40, 40, 40, 255},
|
||||
btn_bg_hot = Color { 60, 60, 70, 255},
|
||||
btn_bg_active = Color { 90, 100, 130, 255},
|
||||
|
||||
input_box_bg = Color { 20, 20, 20, 255},
|
||||
input_box_bg_hot = Color { 25, 25, 25, 255},
|
||||
input_box_bg_active = Color { 15, 15, 15, 255},
|
||||
|
||||
resize_hndl_default = Color_Transparent,
|
||||
resize_hndl_hot = Color { 72, 72, 72, 90},
|
||||
resize_hndl_active = Color { 88, 88, 88, 90},
|
||||
|
||||
table_even_bg_color = Color { 35, 35, 35, 255},
|
||||
table_odd_bg_color = Color { 30, 30, 30, 255},
|
||||
|
||||
text_default = Color {120, 117, 115, 255},
|
||||
text_hot = Color {180, 180, 180, 255},
|
||||
text_active = Color {240, 240, 240, 255},
|
||||
|
||||
translucent_panel = Color { 10, 10, 10, 50},
|
||||
|
||||
window_bar_border = Color { 64, 64, 64, 255}, // border_default
|
||||
window_bar_bg = Color{35, 35, 35, 255},
|
||||
window_btn_close_bg_hot = Color{45, 35, 35, 255},
|
||||
|
||||
window_panel_bg = Color { 10, 10, 10, 50}, // translucent_panel
|
||||
window_panel_border = Color{24, 24, 24, 255},
|
||||
}
|
||||
|
||||
App_Thm_Light :: AppColorTheme {
|
||||
light_limit = Color {195, 195, 195, 255},
|
||||
dark_limit = Color { 60, 60, 60, 255},
|
||||
|
||||
bg = Color {135, 135, 135, 255},
|
||||
|
||||
border_default = Color { 174, 174, 174, 255},
|
||||
|
||||
btn_bg_default = Color { 160, 160, 160, 255},
|
||||
btn_bg_hot = Color { 145, 145, 155, 255},
|
||||
btn_bg_active = Color { 124, 124, 136, 255},
|
||||
|
||||
input_box_bg = Color {115, 115, 115, 255},
|
||||
input_box_bg_hot = Color {125, 125, 125, 255},
|
||||
input_box_bg_active = Color {105, 105, 105, 255},
|
||||
|
||||
resize_hndl_default = Color_Transparent,
|
||||
resize_hndl_hot = Color { 95, 95, 95, 90},
|
||||
resize_hndl_active = Color { 80, 80, 80, 90},
|
||||
|
||||
table_even_bg_color = Color {150, 150, 150, 255},
|
||||
table_odd_bg_color = Color {160, 160, 160, 255},
|
||||
|
||||
text_default = Color { 55, 55, 55, 255},
|
||||
text_hot = Color { 85, 85, 85, 255},
|
||||
text_active = Color { 45, 45, 49, 255},
|
||||
|
||||
translucent_panel = Color { 110, 110, 110, 50},
|
||||
|
||||
window_bar_border = Color{ 174, 174, 174, 255}, // border_default
|
||||
window_bar_bg = Color{ 155, 155, 155, 255},
|
||||
window_btn_close_bg_hot = Color{ 145, 135, 135, 255},
|
||||
|
||||
window_panel_bg = Color {135, 135, 135, 50}, // translucent_panel
|
||||
window_panel_border = Color{184, 184, 184, 255},
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
Memory_App.state = state
|
||||
using state
|
||||
|
||||
// Setup Persistent Slab
|
||||
// Setup Persistent Slabs & String Cache
|
||||
{
|
||||
alignment := uint(mem.DEFAULT_ALIGNMENT)
|
||||
|
||||
@ -93,14 +93,24 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
verify( alloc_error == .None, "Failed to allocate transient slab" )
|
||||
|
||||
transient_clear_time = 120 // Seconds, 2 Minutes
|
||||
|
||||
string_cache = str_cache_init()
|
||||
}
|
||||
|
||||
string_cache = str_cache_init()
|
||||
|
||||
// Setup input frame poll references
|
||||
input = & input_data[1]
|
||||
input_prev = & input_data[0]
|
||||
for & input in input_data {
|
||||
using input
|
||||
error : AllocatorError
|
||||
keyboard_events.keys_pressed, error = array_init_reserve(KeyboardKey, persistent_slab_allocator(), Kilo)
|
||||
ensure(error == AllocatorError.None, "Failed to allocate input.keyboard_events.keys_pressed array")
|
||||
keyboard_events.chars_pressed, error = array_init_reserve(rune, persistent_slab_allocator(), Kilo)
|
||||
ensure(error == AllocatorError.None, "Failed to allocate input.keyboard_events.chars_pressed array")
|
||||
}
|
||||
|
||||
// Configuration Load
|
||||
// TODO(Ed): Make this actually load from an ini
|
||||
{
|
||||
using config
|
||||
resolution_width = 1000
|
||||
@ -119,6 +129,8 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
timing_fps_moving_avg_alpha = 0.9
|
||||
|
||||
ui_resize_border_width = 5
|
||||
|
||||
color_theme = App_Thm_Dusk
|
||||
}
|
||||
|
||||
Desired_OS_Scheduler_MS :: 1
|
||||
@ -182,6 +194,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
}
|
||||
|
||||
// Demo project setup
|
||||
// TODO(Ed): This will eventually have to occur when the user either creates or loads a workspace. I don't know
|
||||
{
|
||||
using project
|
||||
path = str_intern("./")
|
||||
@ -318,10 +331,12 @@ tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32
|
||||
|
||||
rl.PollInputEvents()
|
||||
|
||||
debug.draw_ui_box_bounds_points = true
|
||||
debug.draw_ui_box_bounds_points = false
|
||||
debug.draw_UI_padding_bounds = false
|
||||
debug.draw_ui_content_bounds = true
|
||||
debug.draw_ui_content_bounds = false
|
||||
|
||||
config.color_theme = App_Thm_Light
|
||||
// config.color_theme = App_Thm_Dusk
|
||||
should_close = update( host_delta_time )
|
||||
render()
|
||||
|
||||
|
@ -43,7 +43,7 @@ render :: proc()
|
||||
render_mode_3d()
|
||||
|
||||
rl.BeginDrawing()
|
||||
rl.ClearBackground( Color_ThmDark_BG )
|
||||
rl.ClearBackground( app_color_theme().bg )
|
||||
|
||||
render_mode_2d_workspace()
|
||||
render_mode_screenspace()
|
||||
@ -252,7 +252,7 @@ render_mode_screenspace :: proc ()
|
||||
{
|
||||
// debug_text( "Screen Width : %v", rl.GetScreenWidth () )
|
||||
// debug_text( "Screen Height: %v", rl.GetScreenHeight() )
|
||||
debug_text( "frametime_target_ms : %f ms", frametime_target_ms )
|
||||
// debug_text( "frametime_target_ms : %f ms", frametime_target_ms )
|
||||
debug_text( "frametime : %f ms", frametime_delta_ms )
|
||||
// debug_text( "frametime_last_elapsed_ms : %f ms", frametime_elapsed_ms )
|
||||
if replay.mode == ReplayMode.Record {
|
||||
@ -261,10 +261,9 @@ render_mode_screenspace :: proc ()
|
||||
if replay.mode == ReplayMode.Playback {
|
||||
debug_text( "Replaying Input")
|
||||
}
|
||||
// debug_text("Zoom Target: %v", project.workspace.zoom_target)
|
||||
}
|
||||
|
||||
debug_text("Zoom Target: %v", project.workspace.zoom_target)
|
||||
|
||||
if debug.mouse_vis {
|
||||
debug_text("Mouse Vertical Wheel: %v", input.mouse.vertical_wheel )
|
||||
debug_text("Mouse Delta : %v", input.mouse.delta )
|
||||
@ -277,34 +276,39 @@ render_mode_screenspace :: proc ()
|
||||
|
||||
ui := & project.workspace.ui
|
||||
|
||||
debug_text("Box Count (Workspace): %v", ui.built_box_count )
|
||||
if false
|
||||
{
|
||||
debug_text("Box Count (Workspace): %v", ui.built_box_count )
|
||||
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Worksapce Hot Box : %v", hot_box.label.str )
|
||||
debug_text("Workspace Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
}
|
||||
if active_box != nil{
|
||||
debug_text("Workspace Active Box: %v", active_box.label.str )
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Worksapce Hot Box : %v", hot_box.label.str )
|
||||
debug_text("Workspace Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
}
|
||||
if active_box != nil{
|
||||
debug_text("Workspace Active Box: %v", active_box.label.str )
|
||||
}
|
||||
}
|
||||
|
||||
ui = & screen_ui
|
||||
|
||||
debug_text("Box Count: %v", ui.built_box_count )
|
||||
if true
|
||||
{
|
||||
debug_text("Box Count: %v", ui.built_box_count )
|
||||
|
||||
hot_box = ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box = ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Hot Box : %v", hot_box.label.str )
|
||||
debug_text("Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
}
|
||||
if active_box != nil{
|
||||
debug_text("Active Box: %v", active_box.label.str )
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Hot Box : %v", hot_box.label.str )
|
||||
debug_text("Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
}
|
||||
if active_box != nil{
|
||||
debug_text("Active Box: %v", active_box.label.str )
|
||||
}
|
||||
}
|
||||
|
||||
view := view_get_bounds()
|
||||
|
||||
debug.draw_debug_text_y = 14
|
||||
|
||||
// Define the triangle vertices and colors
|
||||
|
@ -239,7 +239,7 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
// test_hover_n_click()
|
||||
// test_draggable()
|
||||
// test_text_box()
|
||||
test_parenting( & default_layout, & frame_style_default )
|
||||
// test_parenting( & default_layout, & frame_style_default )
|
||||
// test_whitespace_ast( & default_layout, & frame_style_default )
|
||||
}
|
||||
//endregion Workspace Imgui Tick
|
||||
|
@ -75,7 +75,7 @@ array_init_reserve :: proc
|
||||
return
|
||||
}
|
||||
|
||||
array_append :: proc( self : ^Array( $ Type), value : Type ) -> AllocatorError
|
||||
array_append_value :: proc( self : ^Array( $ Type), value : Type ) -> AllocatorError
|
||||
{
|
||||
// profile(#procedure)
|
||||
if self.header.num == self.header.capacity
|
||||
@ -91,11 +91,11 @@ array_append :: proc( self : ^Array( $ Type), value : Type ) -> AllocatorError
|
||||
return AllocatorError.None
|
||||
}
|
||||
|
||||
array_append_slice :: proc( using self : ^Array( $ Type ), items : []Type ) -> AllocatorError
|
||||
array_append_array :: proc( using self: ^Array( $ Type), other : Array(Type)) -> AllocatorError
|
||||
{
|
||||
if num + len(items) > capacity
|
||||
if num + other.num > capacity
|
||||
{
|
||||
grow_result := array_grow( self, capacity )
|
||||
grow_result := array_grow( self, num + other.num )
|
||||
if grow_result != AllocatorError.None {
|
||||
return grow_result
|
||||
}
|
||||
@ -106,9 +106,31 @@ array_append_slice :: proc( using self : ^Array( $ Type ), items : []Type ) -> A
|
||||
|
||||
// TODO(Ed) : VERIFY VIA DEBUG THIS COPY IS FINE.
|
||||
target := ptr_offset( data, num )
|
||||
copy( slice_ptr(target, capacity - num), items )
|
||||
copy( slice_ptr(target, int(capacity - num)), array_to_slice(other) )
|
||||
|
||||
num += len(items)
|
||||
num += other.num
|
||||
return AllocatorError.None
|
||||
}
|
||||
|
||||
array_append_slice :: proc( using self : ^Array( $ Type ), items : []Type ) -> AllocatorError
|
||||
{
|
||||
items_num :=u64(len(items))
|
||||
if num + items_num > capacity
|
||||
{
|
||||
grow_result := array_grow( self, num + items_num )
|
||||
if grow_result != AllocatorError.None {
|
||||
return grow_result
|
||||
}
|
||||
}
|
||||
|
||||
// Note(Ed) : Original code from gencpp
|
||||
// libc.memcpy( ptr_offset(data, num), raw_data(items), len(items) * size_of(Type) )
|
||||
|
||||
// TODO(Ed) : VERIFY VIA DEBUG THIS COPY IS FINE.
|
||||
target := ptr_offset( data, num )
|
||||
copy( slice_ptr(target, int(capacity - num)), items )
|
||||
|
||||
num += items_num
|
||||
return AllocatorError.None
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,12 @@ add :: proc {
|
||||
add_range2,
|
||||
}
|
||||
|
||||
array_append :: proc {
|
||||
array_append_value,
|
||||
array_append_array,
|
||||
array_append_slice,
|
||||
}
|
||||
|
||||
bivec3 :: proc {
|
||||
bivec3_via_f32s,
|
||||
vec3_to_bivec3,
|
||||
|
@ -1 +1 @@
|
||||
package sectr
|
||||
package sectr
|
||||
|
@ -281,221 +281,13 @@ mouse_world_delta :: #force_inline proc "contextless" () -> Vec2 {
|
||||
|
||||
InputState :: struct {
|
||||
keyboard : KeyboardState,
|
||||
mouse : MouseState
|
||||
mouse : MouseState,
|
||||
|
||||
keyboard_events : KeyboardEvents,
|
||||
}
|
||||
|
||||
import "core:os"
|
||||
import c "core:c/libc"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
poll_input :: proc( old, new : ^ InputState )
|
||||
{
|
||||
profile(#procedure)
|
||||
input_process_digital_btn :: proc( old_state, new_state : ^ DigitalBtn, is_down : b32 )
|
||||
{
|
||||
new_state.ended_down = is_down
|
||||
had_transition := old_state.ended_down != new_state.ended_down
|
||||
if had_transition {
|
||||
new_state.half_transitions += 1
|
||||
}
|
||||
else {
|
||||
new_state.half_transitions = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Keyboard
|
||||
{
|
||||
// profile("Keyboard")
|
||||
check_range :: proc( old, new : ^ InputState, start, end : i32 )
|
||||
{
|
||||
for id := start; id < end; id += 1
|
||||
{
|
||||
// TODO(Ed) : LOOK OVER THIS...
|
||||
entry_old := & old.keyboard.keys[id - 1]
|
||||
entry_new := & new.keyboard.keys[id - 1]
|
||||
|
||||
key_id := cast(KeyboardKey) id
|
||||
|
||||
is_down := cast(b32) rl.IsKeyDown( to_raylib_key(id) )
|
||||
input_process_digital_btn( entry_old, entry_new, is_down )
|
||||
}
|
||||
}
|
||||
|
||||
DeadBound_1 :: 0x0A
|
||||
DeadBound_2 :: 0x2E
|
||||
DeadBound_3 :: 0x19
|
||||
DeadBound_4 :: 0x3F
|
||||
check_range( old, new, cast(i32) KeyboardKey.enter, DeadBound_1 )
|
||||
check_range( old, new, cast(i32) KeyboardKey.caps_lock, DeadBound_2 )
|
||||
check_range( old, new, cast(i32) KeyboardKey.escape, DeadBound_3 )
|
||||
check_range( old, new, cast(i32) KeyboardKey.backtick, DeadBound_4 )
|
||||
check_range( old, new, cast(i32) KeyboardKey.A, cast(i32) KeyboardKey.count )
|
||||
}
|
||||
|
||||
// Mouse
|
||||
{
|
||||
// profile("Mouse")
|
||||
// Process Buttons
|
||||
for id : i32 = 0; id < i32(MouseBtn.count); id += 1
|
||||
{
|
||||
old_btn := & old.mouse.btns[id]
|
||||
new_btn := & new.mouse.btns[id]
|
||||
|
||||
mouse_id := cast(MouseBtn) id
|
||||
|
||||
is_down := cast(b32) rl.IsMouseButtonDown( to_raylib_mouse_btn(id) )
|
||||
input_process_digital_btn( old_btn, new_btn, is_down )
|
||||
}
|
||||
|
||||
new.mouse.raw_pos = rl.GetMousePosition()
|
||||
new.mouse.pos = render_to_screen_pos(new.mouse.raw_pos)
|
||||
new.mouse.delta = rl.GetMouseDelta() * {1, -1}
|
||||
new.mouse.vertical_wheel = rl.GetMouseWheelMove()
|
||||
}
|
||||
}
|
||||
|
||||
record_input :: proc( replay_file : os.Handle, input : ^ InputState ) {
|
||||
raw_data := slice_ptr( transmute(^ byte) input, size_of(InputState) )
|
||||
file_write( replay_file, raw_data )
|
||||
}
|
||||
|
||||
play_input :: proc( replay_file : os.Handle, input : ^ InputState ) {
|
||||
raw_data := slice_ptr( transmute(^ byte) input, size_of(InputState) )
|
||||
total_read, result_code := file_read( replay_file, raw_data )
|
||||
if result_code == os.ERROR_HANDLE_EOF {
|
||||
file_rewind( replay_file )
|
||||
load_snapshot( & Memory_App.snapshot )
|
||||
}
|
||||
}
|
||||
|
||||
to_raylib_key :: proc( key : i32 ) -> rl.KeyboardKey {
|
||||
@static raylib_key_lookup_table := [?] rl.KeyboardKey {
|
||||
rl.KeyboardKey.KEY_NULL,
|
||||
rl.KeyboardKey.ENTER,
|
||||
rl.KeyboardKey.TAB,
|
||||
rl.KeyboardKey.SPACE,
|
||||
rl.KeyboardKey.LEFT_BRACKET,
|
||||
rl.KeyboardKey.RIGHT_BRACKET,
|
||||
rl.KeyboardKey.SEMICOLON,
|
||||
rl.KeyboardKey.APOSTROPHE,
|
||||
rl.KeyboardKey.COMMA,
|
||||
rl.KeyboardKey.PERIOD,
|
||||
cast(rl.KeyboardKey) 0, // 0x0A
|
||||
cast(rl.KeyboardKey) 0, // 0x0B
|
||||
cast(rl.KeyboardKey) 0, // 0x0C
|
||||
cast(rl.KeyboardKey) 0, // 0x0D
|
||||
cast(rl.KeyboardKey) 0, // 0x0E
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
rl.KeyboardKey.CAPS_LOCK,
|
||||
rl.KeyboardKey.SCROLL_LOCK,
|
||||
rl.KeyboardKey.NUM_LOCK,
|
||||
rl.KeyboardKey.LEFT_ALT,
|
||||
rl.KeyboardKey.LEFT_SHIFT,
|
||||
rl.KeyboardKey.LEFT_CONTROL,
|
||||
rl.KeyboardKey.RIGHT_ALT,
|
||||
rl.KeyboardKey.RIGHT_SHIFT,
|
||||
rl.KeyboardKey.RIGHT_CONTROL,
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
rl.KeyboardKey.ESCAPE,
|
||||
rl.KeyboardKey.F1,
|
||||
rl.KeyboardKey.F2,
|
||||
rl.KeyboardKey.F3,
|
||||
rl.KeyboardKey.F4,
|
||||
rl.KeyboardKey.F5,
|
||||
rl.KeyboardKey.F7,
|
||||
rl.KeyboardKey.F8,
|
||||
rl.KeyboardKey.F9,
|
||||
rl.KeyboardKey.F10,
|
||||
rl.KeyboardKey.F11,
|
||||
rl.KeyboardKey.F12,
|
||||
rl.KeyboardKey.PRINT_SCREEN,
|
||||
rl.KeyboardKey.PAUSE,
|
||||
cast(rl.KeyboardKey) 0, // 0x2E
|
||||
rl.KeyboardKey.GRAVE,
|
||||
cast(rl.KeyboardKey) '0',
|
||||
cast(rl.KeyboardKey) '1',
|
||||
cast(rl.KeyboardKey) '2',
|
||||
cast(rl.KeyboardKey) '3',
|
||||
cast(rl.KeyboardKey) '4',
|
||||
cast(rl.KeyboardKey) '5',
|
||||
cast(rl.KeyboardKey) '6',
|
||||
cast(rl.KeyboardKey) '7',
|
||||
cast(rl.KeyboardKey) '8',
|
||||
cast(rl.KeyboardKey) '9',
|
||||
rl.KeyboardKey.MINUS,
|
||||
rl.KeyboardKey.EQUAL,
|
||||
rl.KeyboardKey.BACKSPACE,
|
||||
rl.KeyboardKey.BACKSLASH,
|
||||
rl.KeyboardKey.SLASH,
|
||||
cast(rl.KeyboardKey) 0, // 0x3F
|
||||
cast(rl.KeyboardKey) 0, // 0x40
|
||||
rl.KeyboardKey.A,
|
||||
rl.KeyboardKey.B,
|
||||
rl.KeyboardKey.C,
|
||||
rl.KeyboardKey.D,
|
||||
rl.KeyboardKey.E,
|
||||
rl.KeyboardKey.F,
|
||||
rl.KeyboardKey.G,
|
||||
rl.KeyboardKey.H,
|
||||
rl.KeyboardKey.I,
|
||||
rl.KeyboardKey.J,
|
||||
rl.KeyboardKey.K,
|
||||
rl.KeyboardKey.L,
|
||||
rl.KeyboardKey.M,
|
||||
rl.KeyboardKey.N,
|
||||
rl.KeyboardKey.O,
|
||||
rl.KeyboardKey.P,
|
||||
rl.KeyboardKey.Q,
|
||||
rl.KeyboardKey.R,
|
||||
rl.KeyboardKey.S,
|
||||
rl.KeyboardKey.T,
|
||||
rl.KeyboardKey.U,
|
||||
rl.KeyboardKey.V,
|
||||
rl.KeyboardKey.W,
|
||||
rl.KeyboardKey.X,
|
||||
rl.KeyboardKey.Y,
|
||||
rl.KeyboardKey.Z,
|
||||
rl.KeyboardKey.INSERT,
|
||||
rl.KeyboardKey.DELETE,
|
||||
rl.KeyboardKey.HOME,
|
||||
rl.KeyboardKey.END,
|
||||
rl.KeyboardKey.PAGE_UP,
|
||||
rl.KeyboardKey.PAGE_DOWN,
|
||||
rl.KeyboardKey.KP_0,
|
||||
rl.KeyboardKey.KP_1,
|
||||
rl.KeyboardKey.KP_2,
|
||||
rl.KeyboardKey.KP_3,
|
||||
rl.KeyboardKey.KP_4,
|
||||
rl.KeyboardKey.KP_5,
|
||||
rl.KeyboardKey.KP_6,
|
||||
rl.KeyboardKey.KP_7,
|
||||
rl.KeyboardKey.KP_8,
|
||||
rl.KeyboardKey.KP_9,
|
||||
rl.KeyboardKey.KP_DECIMAL,
|
||||
rl.KeyboardKey.KP_EQUAL,
|
||||
rl.KeyboardKey.KP_ADD,
|
||||
rl.KeyboardKey.KP_SUBTRACT,
|
||||
rl.KeyboardKey.KP_MULTIPLY,
|
||||
rl.KeyboardKey.KP_DIVIDE,
|
||||
rl.KeyboardKey.KP_ENTER }
|
||||
return raylib_key_lookup_table[ key ]
|
||||
}
|
||||
|
||||
to_raylib_mouse_btn :: proc( btn : i32 ) -> rl.MouseButton {
|
||||
@static raylib_mouse_btn_lookup_table := [?] rl.MouseButton {
|
||||
rl.MouseButton.LEFT,
|
||||
rl.MouseButton.MIDDLE,
|
||||
rl.MouseButton.RIGHT,
|
||||
rl.MouseButton.SIDE,
|
||||
rl.MouseButton.FORWARD,
|
||||
rl.MouseButton.BACK,
|
||||
rl.MouseButton.EXTRA,
|
||||
}
|
||||
return raylib_mouse_btn_lookup_table[ btn ]
|
||||
// TODO(Ed): Whats the lifetime of these events? (So far we're picking per full-frame)
|
||||
KeyboardEvents :: struct {
|
||||
keys_pressed : Array(KeyboardKey),
|
||||
chars_pressed : Array(rune),
|
||||
}
|
||||
|
350
code/sectr/input/input_raylib.odin
Normal file
350
code/sectr/input/input_raylib.odin
Normal file
@ -0,0 +1,350 @@
|
||||
package sectr
|
||||
|
||||
import "base:runtime"
|
||||
import "core:os"
|
||||
import c "core:c/libc"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
poll_input :: proc( old, new : ^ InputState )
|
||||
{
|
||||
profile(#procedure)
|
||||
input_process_digital_btn :: proc( old_state, new_state : ^ DigitalBtn, is_down : b32 )
|
||||
{
|
||||
new_state.ended_down = is_down
|
||||
had_transition := old_state.ended_down != new_state.ended_down
|
||||
if had_transition {
|
||||
new_state.half_transitions += 1
|
||||
}
|
||||
else {
|
||||
new_state.half_transitions = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Keyboard
|
||||
{
|
||||
// profile("Keyboard")
|
||||
check_range :: proc( old, new : ^ InputState, start, end : i32 )
|
||||
{
|
||||
for id := start; id < end; id += 1
|
||||
{
|
||||
// TODO(Ed) : LOOK OVER THIS...
|
||||
entry_old := & old.keyboard.keys[id - 1]
|
||||
entry_new := & new.keyboard.keys[id - 1]
|
||||
|
||||
key_id := cast(KeyboardKey) id
|
||||
|
||||
is_down := cast(b32) rl.IsKeyDown( to_raylib_key(id) )
|
||||
input_process_digital_btn( entry_old, entry_new, is_down )
|
||||
}
|
||||
}
|
||||
|
||||
DeadBound_1 :: 0x0A
|
||||
DeadBound_2 :: 0x2E
|
||||
DeadBound_3 :: 0x19
|
||||
DeadBound_4 :: 0x3F
|
||||
check_range( old, new, cast(i32) KeyboardKey.enter, DeadBound_1 )
|
||||
check_range( old, new, cast(i32) KeyboardKey.caps_lock, DeadBound_2 )
|
||||
check_range( old, new, cast(i32) KeyboardKey.escape, DeadBound_3 )
|
||||
check_range( old, new, cast(i32) KeyboardKey.backtick, DeadBound_4 )
|
||||
check_range( old, new, cast(i32) KeyboardKey.A, cast(i32) KeyboardKey.count )
|
||||
|
||||
swap( & old.keyboard_events.keys_pressed, & new.keyboard_events.keys_pressed )
|
||||
swap( & old.keyboard_events.chars_pressed, & new.keyboard_events.chars_pressed )
|
||||
|
||||
array_clear( new.keyboard_events.keys_pressed )
|
||||
array_clear( new.keyboard_events.chars_pressed )
|
||||
|
||||
for key_pressed := rl.GetKeyPressed(); key_pressed != rl.KeyboardKey.KEY_NULL; key_pressed = rl.GetKeyPressed() {
|
||||
array_append( & new.keyboard_events.keys_pressed, to_key_from_raylib(key_pressed))
|
||||
}
|
||||
for char_pressed := rl.GetCharPressed(); char_pressed != cast(rune)0; char_pressed = rl.GetCharPressed() {
|
||||
array_append( & new.keyboard_events.chars_pressed, char_pressed)
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse
|
||||
{
|
||||
// profile("Mouse")
|
||||
// Process Buttons
|
||||
for id : i32 = 0; id < i32(MouseBtn.count); id += 1
|
||||
{
|
||||
old_btn := & old.mouse.btns[id]
|
||||
new_btn := & new.mouse.btns[id]
|
||||
|
||||
mouse_id := cast(MouseBtn) id
|
||||
|
||||
is_down := cast(b32) rl.IsMouseButtonDown( to_raylib_mouse_btn(id) )
|
||||
input_process_digital_btn( old_btn, new_btn, is_down )
|
||||
}
|
||||
|
||||
new.mouse.raw_pos = rl.GetMousePosition()
|
||||
new.mouse.pos = render_to_screen_pos(new.mouse.raw_pos)
|
||||
new.mouse.delta = rl.GetMouseDelta() * {1, -1}
|
||||
new.mouse.vertical_wheel = rl.GetMouseWheelMove()
|
||||
}
|
||||
}
|
||||
|
||||
record_input :: proc( replay_file : os.Handle, input : ^ InputState ) {
|
||||
raw_data := slice_ptr( transmute(^ byte) input, size_of(InputState) )
|
||||
file_write( replay_file, raw_data )
|
||||
}
|
||||
|
||||
play_input :: proc( replay_file : os.Handle, input : ^ InputState ) {
|
||||
raw_data := slice_ptr( transmute(^ byte) input, size_of(InputState) )
|
||||
total_read, result_code := file_read( replay_file, raw_data )
|
||||
if result_code == os.ERROR_HANDLE_EOF {
|
||||
file_rewind( replay_file )
|
||||
load_snapshot( & Memory_App.snapshot )
|
||||
}
|
||||
}
|
||||
|
||||
to_key_from_raylib :: proc( key : rl.KeyboardKey ) -> KeyboardKey {
|
||||
@static lookup_table := [?] KeyboardKey {
|
||||
KeyboardKey.null,
|
||||
KeyboardKey.enter,
|
||||
KeyboardKey.tab,
|
||||
KeyboardKey.space,
|
||||
KeyboardKey.bracket_open,
|
||||
KeyboardKey.bracket_close,
|
||||
KeyboardKey.semicolon,
|
||||
KeyboardKey.apostrophe,
|
||||
KeyboardKey.comma,
|
||||
KeyboardKey.period,
|
||||
cast(KeyboardKey) 0, // 0x0A
|
||||
cast(KeyboardKey) 0, // 0x0B
|
||||
cast(KeyboardKey) 0, // 0x0C
|
||||
cast(KeyboardKey) 0, // 0x0D
|
||||
cast(KeyboardKey) 0, // 0x0E
|
||||
cast(KeyboardKey) 0, // 0x0F
|
||||
KeyboardKey.caps_lock,
|
||||
KeyboardKey.scroll_lock,
|
||||
KeyboardKey.num_lock,
|
||||
KeyboardKey.left_alt,
|
||||
KeyboardKey.left_shit,
|
||||
KeyboardKey.left_control,
|
||||
KeyboardKey.right_alt,
|
||||
KeyboardKey.right_shift,
|
||||
KeyboardKey.right_control,
|
||||
cast(KeyboardKey) 0, // 0x0F
|
||||
cast(KeyboardKey) 0, // 0x0F
|
||||
cast(KeyboardKey) 0, // 0x0F
|
||||
cast(KeyboardKey) 0, // 0x0F
|
||||
cast(KeyboardKey) 0, // 0x0F
|
||||
cast(KeyboardKey) 0, // 0x0F
|
||||
cast(KeyboardKey) 0, // 0x0F
|
||||
KeyboardKey.escape,
|
||||
KeyboardKey.F1,
|
||||
KeyboardKey.F2,
|
||||
KeyboardKey.F3,
|
||||
KeyboardKey.F4,
|
||||
KeyboardKey.F5,
|
||||
KeyboardKey.F7,
|
||||
KeyboardKey.F8,
|
||||
KeyboardKey.F9,
|
||||
KeyboardKey.F10,
|
||||
KeyboardKey.F11,
|
||||
KeyboardKey.F12,
|
||||
KeyboardKey.print_screen,
|
||||
KeyboardKey.pause,
|
||||
cast(KeyboardKey) 0, // 0x2E
|
||||
KeyboardKey.backtick,
|
||||
KeyboardKey.nrow_0,
|
||||
KeyboardKey.nrow_1,
|
||||
KeyboardKey.nrow_2,
|
||||
KeyboardKey.nrow_3,
|
||||
KeyboardKey.nrow_4,
|
||||
KeyboardKey.nrow_5,
|
||||
KeyboardKey.nrow_6,
|
||||
KeyboardKey.nrow_7,
|
||||
KeyboardKey.nrow_8,
|
||||
KeyboardKey.nrow_9,
|
||||
KeyboardKey.hyphen,
|
||||
KeyboardKey.equals,
|
||||
KeyboardKey.backspace,
|
||||
KeyboardKey.backslash,
|
||||
KeyboardKey.slash,
|
||||
cast(KeyboardKey) 0, // 0x3F
|
||||
cast(KeyboardKey) 0, // 0x40
|
||||
KeyboardKey.A,
|
||||
KeyboardKey.B,
|
||||
KeyboardKey.C,
|
||||
KeyboardKey.D,
|
||||
KeyboardKey.E,
|
||||
KeyboardKey.F,
|
||||
KeyboardKey.G,
|
||||
KeyboardKey.H,
|
||||
KeyboardKey.I,
|
||||
KeyboardKey.J,
|
||||
KeyboardKey.K,
|
||||
KeyboardKey.L,
|
||||
KeyboardKey.M,
|
||||
KeyboardKey.N,
|
||||
KeyboardKey.O,
|
||||
KeyboardKey.P,
|
||||
KeyboardKey.Q,
|
||||
KeyboardKey.R,
|
||||
KeyboardKey.S,
|
||||
KeyboardKey.T,
|
||||
KeyboardKey.U,
|
||||
KeyboardKey.V,
|
||||
KeyboardKey.W,
|
||||
KeyboardKey.X,
|
||||
KeyboardKey.Y,
|
||||
KeyboardKey.Z,
|
||||
KeyboardKey.insert,
|
||||
KeyboardKey.delete,
|
||||
KeyboardKey.home,
|
||||
KeyboardKey.end,
|
||||
KeyboardKey.page_up,
|
||||
KeyboardKey.page_down,
|
||||
KeyboardKey.npad_0,
|
||||
KeyboardKey.npad_1,
|
||||
KeyboardKey.npad_2,
|
||||
KeyboardKey.npad_3,
|
||||
KeyboardKey.npad_4,
|
||||
KeyboardKey.npad_5,
|
||||
KeyboardKey.npad_6,
|
||||
KeyboardKey.npad_7,
|
||||
KeyboardKey.npad_8,
|
||||
KeyboardKey.npad_9,
|
||||
KeyboardKey.npad_decimal,
|
||||
KeyboardKey.npad_equals,
|
||||
KeyboardKey.npad_plus,
|
||||
KeyboardKey.npad_minus,
|
||||
KeyboardKey.npad_multiply,
|
||||
KeyboardKey.npad_divide,
|
||||
KeyboardKey.npad_enter, }
|
||||
return lookup_table[key]
|
||||
}
|
||||
|
||||
to_raylib_key :: proc( key : i32 ) -> rl.KeyboardKey
|
||||
{
|
||||
@static raylib_key_lookup_table := [?] rl.KeyboardKey {
|
||||
rl.KeyboardKey.KEY_NULL,
|
||||
rl.KeyboardKey.ENTER,
|
||||
rl.KeyboardKey.TAB,
|
||||
rl.KeyboardKey.SPACE,
|
||||
rl.KeyboardKey.LEFT_BRACKET,
|
||||
rl.KeyboardKey.RIGHT_BRACKET,
|
||||
rl.KeyboardKey.SEMICOLON,
|
||||
rl.KeyboardKey.APOSTROPHE,
|
||||
rl.KeyboardKey.COMMA,
|
||||
rl.KeyboardKey.PERIOD,
|
||||
cast(rl.KeyboardKey) 0, // 0x0A
|
||||
cast(rl.KeyboardKey) 0, // 0x0B
|
||||
cast(rl.KeyboardKey) 0, // 0x0C
|
||||
cast(rl.KeyboardKey) 0, // 0x0D
|
||||
cast(rl.KeyboardKey) 0, // 0x0E
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
rl.KeyboardKey.CAPS_LOCK,
|
||||
rl.KeyboardKey.SCROLL_LOCK,
|
||||
rl.KeyboardKey.NUM_LOCK,
|
||||
rl.KeyboardKey.LEFT_ALT,
|
||||
rl.KeyboardKey.LEFT_SHIFT,
|
||||
rl.KeyboardKey.LEFT_CONTROL,
|
||||
rl.KeyboardKey.RIGHT_ALT,
|
||||
rl.KeyboardKey.RIGHT_SHIFT,
|
||||
rl.KeyboardKey.RIGHT_CONTROL,
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
cast(rl.KeyboardKey) 0, // 0x0F
|
||||
rl.KeyboardKey.ESCAPE,
|
||||
rl.KeyboardKey.F1,
|
||||
rl.KeyboardKey.F2,
|
||||
rl.KeyboardKey.F3,
|
||||
rl.KeyboardKey.F4,
|
||||
rl.KeyboardKey.F5,
|
||||
rl.KeyboardKey.F7,
|
||||
rl.KeyboardKey.F8,
|
||||
rl.KeyboardKey.F9,
|
||||
rl.KeyboardKey.F10,
|
||||
rl.KeyboardKey.F11,
|
||||
rl.KeyboardKey.F12,
|
||||
rl.KeyboardKey.PRINT_SCREEN,
|
||||
rl.KeyboardKey.PAUSE,
|
||||
cast(rl.KeyboardKey) 0, // 0x2E
|
||||
rl.KeyboardKey.GRAVE,
|
||||
cast(rl.KeyboardKey) '0',
|
||||
cast(rl.KeyboardKey) '1',
|
||||
cast(rl.KeyboardKey) '2',
|
||||
cast(rl.KeyboardKey) '3',
|
||||
cast(rl.KeyboardKey) '4',
|
||||
cast(rl.KeyboardKey) '5',
|
||||
cast(rl.KeyboardKey) '6',
|
||||
cast(rl.KeyboardKey) '7',
|
||||
cast(rl.KeyboardKey) '8',
|
||||
cast(rl.KeyboardKey) '9',
|
||||
rl.KeyboardKey.MINUS,
|
||||
rl.KeyboardKey.EQUAL,
|
||||
rl.KeyboardKey.BACKSPACE,
|
||||
rl.KeyboardKey.BACKSLASH,
|
||||
rl.KeyboardKey.SLASH,
|
||||
cast(rl.KeyboardKey) 0, // 0x3F
|
||||
cast(rl.KeyboardKey) 0, // 0x40
|
||||
rl.KeyboardKey.A,
|
||||
rl.KeyboardKey.B,
|
||||
rl.KeyboardKey.C,
|
||||
rl.KeyboardKey.D,
|
||||
rl.KeyboardKey.E,
|
||||
rl.KeyboardKey.F,
|
||||
rl.KeyboardKey.G,
|
||||
rl.KeyboardKey.H,
|
||||
rl.KeyboardKey.I,
|
||||
rl.KeyboardKey.J,
|
||||
rl.KeyboardKey.K,
|
||||
rl.KeyboardKey.L,
|
||||
rl.KeyboardKey.M,
|
||||
rl.KeyboardKey.N,
|
||||
rl.KeyboardKey.O,
|
||||
rl.KeyboardKey.P,
|
||||
rl.KeyboardKey.Q,
|
||||
rl.KeyboardKey.R,
|
||||
rl.KeyboardKey.S,
|
||||
rl.KeyboardKey.T,
|
||||
rl.KeyboardKey.U,
|
||||
rl.KeyboardKey.V,
|
||||
rl.KeyboardKey.W,
|
||||
rl.KeyboardKey.X,
|
||||
rl.KeyboardKey.Y,
|
||||
rl.KeyboardKey.Z,
|
||||
rl.KeyboardKey.INSERT,
|
||||
rl.KeyboardKey.DELETE,
|
||||
rl.KeyboardKey.HOME,
|
||||
rl.KeyboardKey.END,
|
||||
rl.KeyboardKey.PAGE_UP,
|
||||
rl.KeyboardKey.PAGE_DOWN,
|
||||
rl.KeyboardKey.KP_0,
|
||||
rl.KeyboardKey.KP_1,
|
||||
rl.KeyboardKey.KP_2,
|
||||
rl.KeyboardKey.KP_3,
|
||||
rl.KeyboardKey.KP_4,
|
||||
rl.KeyboardKey.KP_5,
|
||||
rl.KeyboardKey.KP_6,
|
||||
rl.KeyboardKey.KP_7,
|
||||
rl.KeyboardKey.KP_8,
|
||||
rl.KeyboardKey.KP_9,
|
||||
rl.KeyboardKey.KP_DECIMAL,
|
||||
rl.KeyboardKey.KP_EQUAL,
|
||||
rl.KeyboardKey.KP_ADD,
|
||||
rl.KeyboardKey.KP_SUBTRACT,
|
||||
rl.KeyboardKey.KP_MULTIPLY,
|
||||
rl.KeyboardKey.KP_DIVIDE,
|
||||
rl.KeyboardKey.KP_ENTER, }
|
||||
return raylib_key_lookup_table[ key ]
|
||||
}
|
||||
|
||||
to_raylib_mouse_btn :: proc( btn : i32 ) -> rl.MouseButton {
|
||||
@static raylib_mouse_btn_lookup_table := [?] rl.MouseButton {
|
||||
rl.MouseButton.LEFT,
|
||||
rl.MouseButton.MIDDLE,
|
||||
rl.MouseButton.RIGHT,
|
||||
rl.MouseButton.SIDE,
|
||||
rl.MouseButton.FORWARD,
|
||||
rl.MouseButton.BACK,
|
||||
rl.MouseButton.EXTRA, }
|
||||
return raylib_mouse_btn_lookup_table[ btn ]
|
||||
}
|
@ -101,6 +101,8 @@ Range2 :: struct #raw_union {
|
||||
|
||||
UnitRange2 :: distinct Range2
|
||||
|
||||
range2_zero :: Range2 {}
|
||||
|
||||
range2 :: #force_inline proc "contextless" ( a, b : Vec2 ) -> Range2 {
|
||||
result := Range2 { pts = { a, b } }
|
||||
return result
|
||||
|
7
code/sectr/ui/core/Readme.md
Normal file
7
code/sectr/ui/core/Readme.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Plans
|
||||
|
||||
Eventually want to generalize this core UI as its own library.
|
||||
This will keep track of here whats needed for it to work wihtout the rest of this codebase.
|
||||
|
||||
* Provide UI input state in its own data stucture at the beginning of `ui_build_graph`:
|
||||
*
|
@ -15,6 +15,10 @@ UI_BoxFlag :: enum u64
|
||||
UI_BoxFlags :: bit_set[UI_BoxFlag; u64]
|
||||
// UI_BoxFlag_Scroll :: UI_BoxFlags { .Scroll_X, .Scroll_Y }
|
||||
|
||||
UI_NavLinks :: struct {
|
||||
left, right, up, down : ^UI_Box,
|
||||
}
|
||||
|
||||
UI_RenderBoxInfo :: struct {
|
||||
using computed : UI_Computed,
|
||||
using style : UI_Style,
|
||||
@ -26,12 +30,15 @@ UI_RenderBoxInfo :: struct {
|
||||
UI_Box :: struct {
|
||||
// Cache ID
|
||||
key : UI_Key,
|
||||
// label : string,
|
||||
label : StrRunesPair,
|
||||
text : StrRunesPair,
|
||||
|
||||
// Regenerated per frame.
|
||||
|
||||
nav : UI_NavLinks,
|
||||
// signal_callback : #type proc(),
|
||||
|
||||
|
||||
// first, last : The first and last child of this box
|
||||
// prev, next : The adjacent neighboring boxes who are children of to the same parent
|
||||
using links : DLL_NodeFull( UI_Box ),
|
||||
@ -129,7 +136,7 @@ ui_box_tranverse_next :: proc "contextless" ( box : ^ UI_Box ) -> (^ UI_Box)
|
||||
{
|
||||
// Check to make sure parent is present on the screen, if its not don't bother.
|
||||
is_app_ui := ui_context == & screen_ui
|
||||
if intersects_range2( view_get_bounds(), box.computed.bounds)
|
||||
if intersects_range2( ui_view_bounds(), box.computed.bounds)
|
||||
{
|
||||
return box.first
|
||||
}
|
@ -16,13 +16,17 @@ LayoutAlign_OriginTL_Bottom :: Vec2{0.5, 1}
|
||||
LayoutAlign_OriginTL_BottomLeft :: Vec2{ 0, 1}
|
||||
LayoutAlign_OriginTL_BottomRight :: Vec2{ 1, 1}
|
||||
|
||||
// LayoutAlign_OriginTL_
|
||||
|
||||
Layout_OriginCenter_Centered :: Vec2{0.5, 0.5}
|
||||
|
||||
|
||||
|
||||
|
||||
UI_Align_Presets_Struct :: struct {
|
||||
origin_tl_centered : Vec2,
|
||||
text_centered : Vec2,
|
||||
}
|
||||
UI_Align_Presets :: UI_Align_Presets_Struct {
|
||||
origin_tl_centered = {0.5, 0.5},
|
||||
text_centered = {0.5, 0.5},
|
||||
}
|
||||
|
||||
|
||||
// The UI_Box's actual positioning and sizing
|
@ -85,9 +85,16 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
|
||||
if .Scale_Width_By_Height_Ratio in layout.flags {
|
||||
adjusted_size.x = adjusted_size.y * layout.size.min.x
|
||||
}
|
||||
else if .Fixed_Width in layout.flags {
|
||||
adjusted_size.x = layout.size.min.x
|
||||
}
|
||||
|
||||
if .Scale_Height_By_Width_Ratio in layout.flags {
|
||||
adjusted_size.y = adjusted_size.x * layout.size.min.y
|
||||
}
|
||||
else if .Fixed_Height in layout.flags {
|
||||
adjusted_size.y = layout.size.min.y
|
||||
}
|
||||
|
||||
if .Size_To_Content in layout.flags {
|
||||
// Preemtively traverse the children of this parent and have them compute their layout.
|
||||
@ -97,14 +104,6 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
|
||||
//ui_compute_children_bounding_area(box)
|
||||
}
|
||||
|
||||
// TODO(Ed): Should this force override all of the previous auto-sizing possible?
|
||||
if .Fixed_Width in layout.flags {
|
||||
adjusted_size.x = layout.size.min.x
|
||||
}
|
||||
if .Fixed_Height in layout.flags {
|
||||
adjusted_size.y = layout.size.min.y
|
||||
}
|
||||
|
||||
// 5. Determine relative position
|
||||
|
||||
origin_center := margined_bounds_origin
|
||||
@ -186,34 +185,3 @@ ui_box_compute_layout_children :: proc( box : ^UI_Box )
|
||||
}
|
||||
}
|
||||
|
||||
ui_core_compute_layout :: proc( ui : ^UI_State )
|
||||
{
|
||||
profile(#procedure)
|
||||
state := get_state()
|
||||
|
||||
root := ui.root
|
||||
{
|
||||
computed := & root.computed
|
||||
style := root.style
|
||||
layout := & root.layout
|
||||
if ui == & state.screen_ui {
|
||||
computed.bounds.min = transmute(Vec2) state.app_window.extent * -1
|
||||
computed.bounds.max = transmute(Vec2) state.app_window.extent
|
||||
}
|
||||
computed.content = computed.bounds
|
||||
}
|
||||
|
||||
for current := root.first; current != nil; current = ui_box_tranverse_next( current )
|
||||
{
|
||||
if ! current.computed.fresh {
|
||||
ui_box_compute_layout( current )
|
||||
}
|
||||
array_append( & ui.render_queue, UI_RenderBoxInfo {
|
||||
current.computed,
|
||||
current.style,
|
||||
current.text,
|
||||
current.layout.font_size,
|
||||
current.layout.border_width,
|
||||
})
|
||||
}
|
||||
}
|
@ -70,13 +70,13 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
|
||||
|
||||
mouse_clickable := UI_BoxFlag.Mouse_Clickable in box.flags
|
||||
keyboard_clickable := UI_BoxFlag.Keyboard_Clickable in box.flags
|
||||
is_focusable := .Focusable in box.flags
|
||||
|
||||
was_hot := (box.hot_delta > 0)
|
||||
was_active := (ui.active == box.key) && (box.active_delta > 0)
|
||||
was_hot := (box.hot_delta > 0)
|
||||
was_disabled := box.disabled_delta > 0
|
||||
// if was_hot {
|
||||
// runtime.debug_trap()
|
||||
// }
|
||||
|
||||
is_focused_locked := is_focusable ? was_active : false
|
||||
|
||||
// Check to see if this box is active
|
||||
if mouse_clickable && signal.cursor_over && left_pressed && was_hot
|
||||
@ -93,14 +93,14 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
|
||||
// TODO(Ed) : Support double-click detection
|
||||
}
|
||||
|
||||
if mouse_clickable && ! signal.cursor_over && left_released
|
||||
if ! is_focused_locked && was_active && mouse_clickable && ! signal.cursor_over && left_released
|
||||
{
|
||||
box.active_delta = 0
|
||||
|
||||
ui.active = UI_Key(0)
|
||||
ui.active_mouse[MouseBtn.Left] = UI_Key(0)
|
||||
|
||||
signal.released = true
|
||||
signal.released = true
|
||||
}
|
||||
|
||||
if keyboard_clickable
|
||||
@ -109,6 +109,7 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
|
||||
}
|
||||
|
||||
// TODO(Ed): Should panning and scrolling get supported here? (problably not...)
|
||||
// We can just report the scroll amount in the signal and have the scrollbox widget handle it
|
||||
// TODO(Ed) : Add scrolling support
|
||||
// if UI_BoxFlag.Scroll_X in box.flags {
|
||||
|
||||
@ -123,39 +124,7 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
|
||||
// if UI_BoxFlag.Pan_Y in box.flags {
|
||||
// }
|
||||
|
||||
is_disabled := UI_BoxFlag.Disabled in box.flags
|
||||
is_hot := ui.hot == box.key
|
||||
is_active := ui.active == box.key
|
||||
|
||||
// TODO(Ed): It should be able to enter hot without mouse_clickable
|
||||
if mouse_clickable && signal.cursor_over && ! is_disabled
|
||||
{
|
||||
hot_vacant := ui.hot == UI_Key(0)
|
||||
active_vacant := ui.active == UI_Key(0)
|
||||
// (active_vacant is_active)
|
||||
if signal.cursor_over && active_vacant
|
||||
{
|
||||
if ! hot_vacant {
|
||||
prev := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
prev.hot_delta = 0
|
||||
}
|
||||
// prev_hot := zpl_hmap_get( ui.prev_cache, u64(ui.hot) )
|
||||
// prev_hot_label := prev_hot != nil ? prev_hot.label.str : ""
|
||||
// log( str_fmt_tmp("Detected HOT via CURSOR OVER: %v is_hot: %v is_active: %v prev_hot: %v", box.label.str, is_hot, is_active, prev_hot_label ))
|
||||
ui.hot = box.key
|
||||
is_hot = true
|
||||
|
||||
ui.hot_start_style = box.style
|
||||
}
|
||||
}
|
||||
else if ! signal.cursor_over && was_hot
|
||||
{
|
||||
ui.hot = UI_Key(0)
|
||||
is_hot = false
|
||||
box.hot_delta = 0
|
||||
}
|
||||
|
||||
if mouse_clickable && signal.cursor_over && left_released
|
||||
if ! is_focused_locked && was_active && mouse_clickable && signal.cursor_over && left_released
|
||||
{
|
||||
box.active_delta = 0
|
||||
|
||||
@ -169,6 +138,39 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
|
||||
ui.last_clicked = box.key
|
||||
}
|
||||
}
|
||||
|
||||
is_disabled := UI_BoxFlag.Disabled in box.flags
|
||||
is_hot := ui.hot == box.key
|
||||
is_active := ui.active == box.key
|
||||
|
||||
// TODO(Ed): It should be able to enter hot without mouse_clickable
|
||||
if mouse_clickable && signal.cursor_over && ! is_disabled
|
||||
{
|
||||
hot_vacant := ui.hot == UI_Key(0)
|
||||
// active_vacant := ui.active == UI_Key(0)
|
||||
if signal.cursor_over //&& active_vacant
|
||||
{
|
||||
if ! hot_vacant {
|
||||
prev := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
prev.hot_delta = 0
|
||||
}
|
||||
// prev_hot := zpl_hmap_get( ui.prev_cache, u64(ui.hot) )
|
||||
// prev_hot_label := prev_hot != nil ? prev_hot.label.str : ""
|
||||
// log( str_fmt_tmp("Detected HOT via CURSOR OVER: %v is_hot: %v is_active: %v prev_hot: %v", box.label.str, is_hot, is_active, prev_hot_label ))
|
||||
ui.hot = box.key
|
||||
is_hot = true
|
||||
|
||||
ui.hot_start_style = box.style
|
||||
signal.hot = true
|
||||
}
|
||||
}
|
||||
else if ! signal.cursor_over && was_hot
|
||||
{
|
||||
ui.hot = UI_Key(0)
|
||||
is_hot = false
|
||||
box.hot_delta = 0
|
||||
}
|
||||
|
||||
// profile_end()
|
||||
|
||||
// State Deltas update
|
@ -206,14 +206,55 @@ ui_graph_build_begin :: proc( ui : ^ UI_State, bounds : Vec2 = {} )
|
||||
ui_parent_push(root)
|
||||
}
|
||||
|
||||
ui_core_compute_layout :: proc( ui : ^UI_State )
|
||||
{
|
||||
profile(#procedure)
|
||||
state := get_state()
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
ui_graph_build_end :: proc( ui : ^UI_State )
|
||||
{
|
||||
profile(#procedure)
|
||||
state := get_state()
|
||||
|
||||
ui_parent_pop() // Should be ui_context.root
|
||||
|
||||
// Regenerate the computed layout if dirty
|
||||
ui_compute_layout( ui )
|
||||
Post_Build_Graph_Traversal:
|
||||
{
|
||||
root := ui.root
|
||||
{
|
||||
computed := & root.computed
|
||||
style := root.style
|
||||
layout := & root.layout
|
||||
if ui == & state.screen_ui {
|
||||
computed.bounds.min = transmute(Vec2) state.app_window.extent * -1
|
||||
computed.bounds.max = transmute(Vec2) state.app_window.extent
|
||||
}
|
||||
computed.content = computed.bounds
|
||||
}
|
||||
for current := root.first; current != nil; current = ui_box_tranverse_next( current )
|
||||
{
|
||||
|
||||
|
||||
if ! current.computed.fresh {
|
||||
ui_box_compute_layout( current )
|
||||
}
|
||||
|
||||
// Enqueue for rendering
|
||||
array_append( & ui.render_queue, UI_RenderBoxInfo {
|
||||
current.computed,
|
||||
current.style,
|
||||
current.text,
|
||||
current.layout.font_size,
|
||||
current.layout.border_width,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
get_state().ui_context = nil
|
||||
}
|
||||
@ -259,4 +300,14 @@ ui_top_ancestor :: #force_inline proc "contextless" ( box : ^UI_Box ) -> (^UI_Bo
|
||||
return ancestor
|
||||
}
|
||||
|
||||
ui_view_bounds :: #force_inline proc "contextless" () -> (range : Range2) {
|
||||
using state := get_state();
|
||||
if ui_context == & screen_ui {
|
||||
return screen_get_bounds()
|
||||
}
|
||||
else {
|
||||
return view_get_bounds()
|
||||
}
|
||||
}
|
||||
|
||||
ui_context :: #force_inline proc() -> ^UI_State { return get_state().ui_context }
|
@ -117,20 +117,6 @@ ui_floating_build :: proc()
|
||||
}
|
||||
lookup.queued = true
|
||||
dll_full_push_back(floating, lookup, nil )
|
||||
// if first == nil {
|
||||
// first = lookup
|
||||
// last = lookup
|
||||
// continue
|
||||
// }
|
||||
// if first == last {
|
||||
// last = lookup
|
||||
// last.prev = first
|
||||
// first.next = last
|
||||
// continue
|
||||
// }
|
||||
// last.next = lookup
|
||||
// lookup.prev = last
|
||||
// last = lookup
|
||||
}
|
||||
array_clear(build_queue)
|
||||
|
||||
@ -140,28 +126,7 @@ ui_floating_build :: proc()
|
||||
if ! entry.queued
|
||||
{
|
||||
ensure(false, "There should be no queue failures yet")
|
||||
|
||||
if entry == first
|
||||
{
|
||||
first = entry.next
|
||||
entry.next = nil
|
||||
continue
|
||||
}
|
||||
if entry == last
|
||||
{
|
||||
last = last.prev
|
||||
last.prev = nil
|
||||
entry.prev = nil
|
||||
continue
|
||||
}
|
||||
|
||||
left := entry.prev
|
||||
right := entry.next
|
||||
|
||||
left.next = right
|
||||
right.prev = left
|
||||
entry.prev = nil
|
||||
entry.next = nil
|
||||
dll_full_pop(to_raise, floating)
|
||||
}
|
||||
|
||||
if entry.builder( entry.captures ) && entry != last && to_raise == nil
|
||||
|
@ -1,5 +1,7 @@
|
||||
package sectr
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
/*
|
||||
Widget Layout Ops
|
||||
*/
|
||||
@ -13,6 +15,7 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay
|
||||
else {
|
||||
container_width = container.computed.content.max.x - container.computed.content.min.x
|
||||
}
|
||||
container_height := container.computed.content.max.y - container.computed.content.min.y
|
||||
|
||||
// do layout calculations for the children
|
||||
total_stretch_ratio : f32 = 0.0
|
||||
@ -21,16 +24,13 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay
|
||||
{
|
||||
using child.layout
|
||||
scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in flags)
|
||||
if .Scale_Width_By_Height_Ratio in flags
|
||||
{
|
||||
size_req_children += size.min.x * container_height
|
||||
continue
|
||||
}
|
||||
if .Fixed_Width in flags
|
||||
{
|
||||
if scaled_width_by_height {
|
||||
height := size.max.y != 0 ? size.max.y : container_width
|
||||
width := height * size.min.x
|
||||
|
||||
size_req_children += width
|
||||
continue
|
||||
}
|
||||
|
||||
size_req_children += size.min.x
|
||||
continue
|
||||
}
|
||||
@ -40,32 +40,45 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay
|
||||
|
||||
avail_flex_space := container_width - size_req_children
|
||||
|
||||
allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 )
|
||||
allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space, container_height : f32 ) -> (space_allocated : f32)
|
||||
{
|
||||
using child.layout
|
||||
if ! (.Fixed_Width in flags) {
|
||||
size.min.x = anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space - child.layout.margins.left - child.layout.margins.right
|
||||
if .Scale_Width_By_Height_Ratio in flags {
|
||||
size.min.y = container_height
|
||||
space_allocated = size.min.x * container_height
|
||||
}
|
||||
else if ! (.Fixed_Width in flags) {
|
||||
size.min.x = anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space
|
||||
space_allocated = size.min.x
|
||||
}
|
||||
else {
|
||||
space_allocated = size.min.x
|
||||
}
|
||||
space_allocated -= child.layout.margins.left - child.layout.margins.right
|
||||
size.min.x -= child.layout.margins.left - child.layout.margins.right
|
||||
flags |= {.Fixed_Width}
|
||||
return
|
||||
}
|
||||
|
||||
space_used : f32 = 0.0
|
||||
switch direction{
|
||||
case .Right_To_Left:
|
||||
for child := container.last; child != nil; child = child.prev {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.layout
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
pos.x = space_used
|
||||
space_used += size.min.x + child.layout.margins.left + child.layout.margins.right
|
||||
child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height)
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
width : f32
|
||||
pos.x = space_used
|
||||
space_used += child_width + child.layout.margins.left + child.layout.margins.right
|
||||
}
|
||||
case .Left_To_Right:
|
||||
for child := container.first; child != nil; child = child.next {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.layout
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
pos.x = space_used
|
||||
space_used += size.min.x + child.layout.margins.left + child.layout.margins.right
|
||||
child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height)
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
width : f32
|
||||
pos.x = space_used
|
||||
space_used += child_width + child.layout.margins.left + child.layout.margins.right
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,9 +136,8 @@ ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_Layou
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.layout
|
||||
anchor = range2({0,0}, {0, 0})
|
||||
// alignment = {0, 0}
|
||||
pos.y = -space_used
|
||||
space_used += size.min.y
|
||||
space_used += size.min.y + child.layout.margins.top + child.layout.margins.bottom
|
||||
size.min.x = container.computed.content.max.x + container.computed.content.min.x
|
||||
}
|
||||
case .Top_To_Bottom:
|
||||
@ -133,9 +145,8 @@ ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_Layou
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.layout
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
// alignment = {0, 0}
|
||||
pos.y = -space_used
|
||||
space_used += size.min.y
|
||||
space_used += size.min.y + child.layout.margins.top + child.layout.margins.bottom
|
||||
size.min.x = container.computed.content.max.x - container.computed.content.min.x
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ ui_widget :: proc( label : string, flags : UI_BoxFlags ) -> (widget : UI_Widget)
|
||||
|
||||
ui_button :: proc( label : string, flags : UI_BoxFlags = {} ) -> (btn : UI_Widget)
|
||||
{
|
||||
btn_flags := UI_BoxFlags { .Mouse_Clickable, .Focusable, .Click_To_Focus }
|
||||
btn_flags := UI_BoxFlags { .Mouse_Clickable }
|
||||
btn.box = ui_box_make( btn_flags | flags, label )
|
||||
btn.signal = ui_signal_from_box( btn.box )
|
||||
return
|
||||
@ -197,6 +197,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
|
||||
}
|
||||
else
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
flags = flags,
|
||||
anchor = range2({},{}),
|
||||
@ -215,7 +216,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
|
||||
corner_radii = {5, 0, 0, 0},
|
||||
blur_size = 0,
|
||||
font = get_state().default_font,
|
||||
text_color = Color_ThmDark_Text_Default,
|
||||
text_color = app_color.text_default,
|
||||
cursor = {},
|
||||
}
|
||||
layout_combo = to_ui_layout_combo(layout)
|
||||
@ -223,12 +224,12 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
|
||||
{
|
||||
using layout_combo.hot
|
||||
using style_combo.hot
|
||||
bg_color = Color_ThmDark_ResizeHandle_Hot
|
||||
bg_color = app_color.resize_hndl_hot
|
||||
}
|
||||
{
|
||||
using layout_combo.active
|
||||
using style_combo.active
|
||||
bg_color = Color_ThmDark_ResizeHandle_Active
|
||||
bg_color = app_color.resize_hndl_active
|
||||
}
|
||||
}
|
||||
theme := UI_Theme {
|
||||
@ -364,7 +365,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
|
||||
}
|
||||
was_dragging = true
|
||||
}
|
||||
else if released && was_dragging
|
||||
else if released// && was_dragging
|
||||
{
|
||||
// This needed to be added as for some reason, this was getting called in screen_ui even when we were resizing with a handle in a worksapce
|
||||
if active_context != ui do return false
|
||||
|
13
ols.json
13
ols.json
@ -1,13 +1,21 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json",
|
||||
"odin_command": "C:/projects/SectrPrototype/toolchain/Odin/odin.exe",
|
||||
"collections": [
|
||||
{
|
||||
"name": "sectr_host",
|
||||
"path": "C:/projects/SectrPrototype/code/host"
|
||||
},
|
||||
{
|
||||
"name": "sectr",
|
||||
"path": "C:/projects/SectrPrototype/code/sectr"
|
||||
},
|
||||
{
|
||||
"name": "thirdparty",
|
||||
"path": "C:/projects/SectrPrototype/thirdparty"
|
||||
}
|
||||
],
|
||||
"odin_command": "C:/projects/SectrPrototype/toolchain/Odin/odin.exe",
|
||||
"enable_document_symbols": true,
|
||||
"enable_document_symbols": false,
|
||||
"enable_fake_methods": true,
|
||||
"enable_format": false,
|
||||
"enable_hover": true,
|
||||
@ -18,5 +26,6 @@
|
||||
"enable_inlay_hints": true,
|
||||
"enable_procedure_context": true,
|
||||
"enable_procedure_snippet": false,
|
||||
"verbose": true,
|
||||
"disable_parser_errors": false
|
||||
}
|
||||
|
84
scripts/gen_flattened_codebase.ps1
Normal file
84
scripts/gen_flattened_codebase.ps1
Normal file
@ -0,0 +1,84 @@
|
||||
cls
|
||||
Write-Host "Reverse Build.ps1"
|
||||
|
||||
$ps_misc = join-path $PSScriptRoot 'helpers/misc.ps1'
|
||||
. $ps_misc
|
||||
|
||||
$path_root = git rev-parse --show-toplevel
|
||||
$path_code = Join-Path $path_root 'code'
|
||||
$path_code_flattened = Join-Path $path_root 'code_flattened'
|
||||
|
||||
if (Test-Path $path_code_flattened) {
|
||||
Remove-Item -Path $path_code_flattened -Recurse -Force -ErrorAction Ignore
|
||||
}
|
||||
New-Item -ItemType Directory -Path $path_code_flattened
|
||||
|
||||
# $whitelist_package = 'sectr'
|
||||
|
||||
function get-flattened-package
|
||||
{
|
||||
param(
|
||||
[string]$pkg_name,
|
||||
[string]$path_pkg_dir,
|
||||
[string]$path_flattend_dir
|
||||
)
|
||||
$files = Get-ChildItem -Path $path_pkg_dir -File -Recurse
|
||||
foreach ($file in $files)
|
||||
{
|
||||
if ($file.Name -eq '.ODIN_MONOLITHIC_PACKAGE') {
|
||||
continue
|
||||
}
|
||||
|
||||
# Read the file line by line to determine the package name, ignoring comments
|
||||
$package_name = $null
|
||||
Get-Content -Path $file.FullName | ForEach-Object {
|
||||
if ($_ -notmatch '^\s*//')
|
||||
{
|
||||
if ($_ -match '^package\s+(\w+)$') {
|
||||
$package_name = $Matches[1]
|
||||
return $false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($pacakge_name -ne $pkg_name) {
|
||||
Write-Host "Warning: The file $($file.FullName) does not contain a valid package declaration."
|
||||
}
|
||||
|
||||
# Calculate relative path and prepend directory names to the file name
|
||||
$relative_path = $file.FullName.Substring($path_pkg_dir.Length + 1)
|
||||
$relative_dir = Split-Path $relative_path -Parent
|
||||
$relative_dir = $relative_dir.Replace('\', '_').Replace('/', '_')
|
||||
|
||||
if ($relative_dir -ne '') {
|
||||
$target_file_name = "$relative_dir" + "_" + $file.Name
|
||||
} else {
|
||||
$target_file_name = $file.Name
|
||||
}
|
||||
|
||||
$target_file_path = Join-Path $path_flattend_dir $target_file_name
|
||||
|
||||
if (-not (Test-Path $target_file_path))
|
||||
{ New-Item -ItemType SymbolicLink -Path $target_file_path -Value $file.FullName }
|
||||
else
|
||||
{ Write-Host "Warning: The link for $($file.FullName) already exists at $target_file_path. Skipping..." }
|
||||
}
|
||||
}
|
||||
|
||||
$path_pkg_gen = join-path $path_code 'gen'
|
||||
$path_pkg_host = join-path $path_code 'host'
|
||||
$path_pkg_sectr = join-path $path_code 'sectr'
|
||||
|
||||
$path_flattend_gen = join-path $path_code_flattened 'gen'
|
||||
$path_flattend_host = join-path $path_code_flattened ' host'
|
||||
$path_flattend_sectr = join-path $path_code_flattened ' sectr'
|
||||
|
||||
verify-path $path_flattend_gen
|
||||
verify-path $path_flattend_host
|
||||
verify-path $path_flattend_sectr
|
||||
|
||||
get-flattened-package 'gen' $path_pkg_gen $path_flattend_gen
|
||||
get-flattened-package 'host' $path_pkg_host $path_flattend_host
|
||||
get-flattened-package 'sectr' $path_pkg_sectr $path_flattend_sectr
|
||||
|
||||
Write-Host "Flattened directory structure for packages created successfully."
|
6
scripts/helpers/misc.ps1
Normal file
6
scripts/helpers/misc.ps1
Normal file
@ -0,0 +1,6 @@
|
||||
function verify-path { param( $path )
|
||||
if (test-path $path) {return $true}
|
||||
|
||||
new-item -ItemType Directory -Path $path
|
||||
return $false
|
||||
}
|
@ -1 +1 @@
|
||||
Subproject commit 67ae530d22c116f86d476743b5dfc978255391d4
|
||||
Subproject commit 389e12a78580362cae32d522ac021d74187d02b5
|
Loading…
Reference in New Issue
Block a user