Preparing skeleton for proper imgui support.
I originally wanted to reference Ryan's UI series along with the RAD Debugger codebase, but that ended up being too convoluted of a route. Instead, I moved on to just doing a deep dive on imgui content I could find to learn from and associated libraries available. I collected my notes so far in this repo [IMGUI_Notes](https://github.com/Ed94/IMGUI_Notes). For now I have the base scaffolding datatype wise for the prototype ui.
This commit is contained in:
parent
9cc0855c03
commit
7332644515
275
code/__Imgui_raddbg/ui.odin
Normal file
275
code/__Imgui_raddbg/ui.odin
Normal file
@ -0,0 +1,275 @@
|
||||
package wip
|
||||
|
||||
// Based off Ryan Fleury's UI Series & Epic's RAD Debugger which directly implements a version of it.
|
||||
// You will see Note(rjf) these are comments directly from the RAD Debugger codebase by Fleury.
|
||||
// TODO(Ed) If I can, I would like this to be its own package, but the nature of packages in odin may make this difficult.
|
||||
|
||||
// TODO(Ed) : This is in Raddbg base_types.h, consider moving outside of UI.
|
||||
Axis2 :: enum i32 {
|
||||
Invalid = -1,
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Count,
|
||||
}
|
||||
|
||||
Corner :: enum i32 {
|
||||
Invalid = -1,
|
||||
_00,
|
||||
_01,
|
||||
_10,
|
||||
_11,
|
||||
TopLeft = _00,
|
||||
TopRight = _01,
|
||||
BottomLeft = _10,
|
||||
BottomRight = _11,
|
||||
Count = 4,
|
||||
}
|
||||
|
||||
// TODO(Ed) : From Raddbg draw.h, consider if needed or covered by raylib.
|
||||
DrawBucket :: struct {
|
||||
// passes : RenderPassList,
|
||||
stack_gen : u64,
|
||||
last_cmd_stack_gen : u64,
|
||||
// DrawBucketStackDeclares
|
||||
}
|
||||
|
||||
// TODO(Ed) : From Raddbg draw.h, consider if needed or covered by raylib.
|
||||
DrawFancyRunList :: struct {
|
||||
placeholder : int
|
||||
}
|
||||
|
||||
// TODO(Ed) : From Raddbg base_string.h, consider if needed or covered by raylib.
|
||||
FuzzyMatchRangeList :: struct {
|
||||
placeholder : int
|
||||
}
|
||||
|
||||
// TODO(Ed): This is in Raddbg os_gfx.h, consider moving outside of UI.
|
||||
OS_Cursor :: enum u32 {
|
||||
Pointer,
|
||||
IBar,
|
||||
Left_Right,
|
||||
Up_Down,
|
||||
Down_Right,
|
||||
Up_Right,
|
||||
Up_Down_left_Right,
|
||||
Hand_Point,
|
||||
Disabled,
|
||||
Count,
|
||||
}
|
||||
|
||||
Range2 :: struct #raw_union{
|
||||
using _ : struct {
|
||||
min, max : Vec2
|
||||
},
|
||||
using _ : struct {
|
||||
p0, p1 : Vec2
|
||||
},
|
||||
using _ : struct {
|
||||
x0, y0 : f32,
|
||||
x1, y1 : f32,
|
||||
},
|
||||
}
|
||||
|
||||
Side :: enum i32 {
|
||||
Invalid = -1,
|
||||
Min = 0,
|
||||
Max = 1,
|
||||
Count
|
||||
}
|
||||
|
||||
UI_FocusKind :: enum u32 {
|
||||
Null,
|
||||
Off,
|
||||
On,
|
||||
Root,
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_IconKind :: enum u32 {
|
||||
Null,
|
||||
Arrow_Up,
|
||||
Arrow_Left,
|
||||
Arrow_Right,
|
||||
Arrow_Down,
|
||||
Caret_Up,
|
||||
Caret_Left,
|
||||
Caret_Right,
|
||||
Caret_Down,
|
||||
Check_Hollow,
|
||||
Check_Filled,
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_IconInfo :: struct {
|
||||
placehodler : int
|
||||
}
|
||||
|
||||
UI_Key :: struct {
|
||||
opaque : [1]u64,
|
||||
}
|
||||
|
||||
UI_Layout :: struct {
|
||||
placeholder : int
|
||||
}
|
||||
|
||||
UI_Nav :: struct {
|
||||
moved : b32,
|
||||
new_p : Vec2i
|
||||
}
|
||||
|
||||
UI_NavDeltaUnit :: enum u32 {
|
||||
Element,
|
||||
Chunk,
|
||||
Whole,
|
||||
End_Point,
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_NavActionFlag :: enum u32 {
|
||||
Keep_Mark,
|
||||
Delete,
|
||||
Copy,
|
||||
Paste,
|
||||
Zero_Delta_On_Select,
|
||||
Pick_Select_Side,
|
||||
Can_At_Line,
|
||||
Explicit_Directional,
|
||||
Replace_And_Commit,
|
||||
}
|
||||
UI_NavActionFlags :: bit_set[UI_NavActionFlag; u32]
|
||||
|
||||
UI_NavAction :: struct {
|
||||
flags : UI_NavActionFlags,
|
||||
delta : Vec2i,
|
||||
delta_unit : UI_NavDeltaUnit,
|
||||
insertion : string,
|
||||
}
|
||||
|
||||
UI_NavActionNode :: struct {
|
||||
next : ^ UI_NavActionNode,
|
||||
last : ^ UI_NavActionNode,
|
||||
action : UI_NavAction
|
||||
}
|
||||
|
||||
UI_NavActionList :: struct {
|
||||
first : ^ UI_NavActionNode,
|
||||
last : ^ UI_NavActionNode,
|
||||
count : u64,
|
||||
}
|
||||
|
||||
UI_NavTextOpFlag :: enum u32 {
|
||||
Invalid,
|
||||
Copy,
|
||||
}
|
||||
UI_NavTextOpFlags :: bit_set[UI_NavTextOpFlag; u32]
|
||||
|
||||
UI_ScrollPt :: struct {
|
||||
idx : i64,
|
||||
offset : f32
|
||||
}
|
||||
UI_ScrollPt2 :: [2]UI_ScrollPt
|
||||
|
||||
UI_Signal :: struct {
|
||||
box : UI_Box,
|
||||
|
||||
cursor_pos : Vec2,
|
||||
drag_delta : Vec2,
|
||||
scroll : Vec2,
|
||||
|
||||
left_clicked : b8,
|
||||
right_clicked : b8,
|
||||
double_clicked : b8,
|
||||
keyboard_clicked : b8,
|
||||
|
||||
pressed : b8,
|
||||
released : b8,
|
||||
dragging : b8,
|
||||
hovering : b8,
|
||||
mouse_over : b8,
|
||||
commit : b8,
|
||||
}
|
||||
|
||||
UI_SizeKind :: enum u32 {
|
||||
Null,
|
||||
Pixels,
|
||||
Points,
|
||||
TextContent,
|
||||
PercentOfParent,
|
||||
ChildrenSum,
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_Size :: struct {
|
||||
kind : UI_SizeKind,
|
||||
value : f32,
|
||||
strictness : f32,
|
||||
}
|
||||
|
||||
UI_Size2 : struct {
|
||||
kind : [Axis2.Count]UI_SizeKind,
|
||||
value : Vec2,
|
||||
strictness : Vec2,
|
||||
}
|
||||
|
||||
UI_TextAlign :: enum u32 {
|
||||
Left,
|
||||
Center,
|
||||
Right,
|
||||
Count
|
||||
}
|
||||
|
||||
ui_key_null :: proc() -> UI_Key {
|
||||
return {}
|
||||
}
|
||||
|
||||
ui_key_from_string :: proc( value : string ) -> UI_Key {
|
||||
return {}
|
||||
}
|
||||
|
||||
ui_key_match :: proc( a, b : UI_Key ) -> b32 {
|
||||
return false
|
||||
}
|
||||
|
||||
ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box) {
|
||||
return nil
|
||||
}
|
||||
|
||||
ui_box_equip_display_string :: proc( box : ^ UI_Box, display_string : string ) {
|
||||
|
||||
}
|
||||
|
||||
ui_box_equip_child_layout_axis :: proc( box : ^ UI_Box, axis : Axis2 ) {
|
||||
|
||||
}
|
||||
|
||||
ui_push_parent :: proc( box : ^ UI_Box ) -> (^ UI_Box) {
|
||||
return nil
|
||||
}
|
||||
|
||||
ui_pop_parent :: proc() -> (^ UI_Box) {
|
||||
return nil
|
||||
}
|
||||
|
||||
ui_signal_from_box :: proc( box : ^ UI_Box ) -> UI_Signal {
|
||||
return {}
|
||||
}
|
||||
|
||||
ui_button :: proc( label : string ) -> UI_Signal {
|
||||
button_flags : UI_BoxFlags =
|
||||
UI_BoxFlags_Clickable & {
|
||||
.Draw_Border,
|
||||
.Draw_Text,
|
||||
.Draw_Background,
|
||||
.Focus_Hot,
|
||||
.Focus_Active,
|
||||
}
|
||||
box := ui_box_make( button_flags, label )
|
||||
signal := ui_signal_from_box( box )
|
||||
return signal
|
||||
}
|
||||
|
||||
ui_spacer :: proc ( label : string = UI_NullLabel ) -> UI_Signal {
|
||||
box := ui_box_make( UI_BoxFlags_Null, label )
|
||||
signal := ui_signal_from_box( box )
|
||||
return signal
|
||||
}
|
172
code/__Imgui_raddbg/ui_box.odin
Normal file
172
code/__Imgui_raddbg/ui_box.odin
Normal file
@ -0,0 +1,172 @@
|
||||
package wip
|
||||
|
||||
UI_BoxFlag :: enum u64 {
|
||||
// Note(rjf) : Interaction
|
||||
Mouse_Clickable,
|
||||
Keyboard_Clickable,
|
||||
Click_To_Focus,
|
||||
Scroll,
|
||||
View_Scroll_X,
|
||||
View_Scroll_Y,
|
||||
View_Clamp_X,
|
||||
View_Clamp_Y,
|
||||
Focus_Active,
|
||||
Focus_Active_Disabled,
|
||||
Focus_Hot,
|
||||
Focus_Hot_Disabled,
|
||||
Default_Focus_Nav_X,
|
||||
Default_Focus_Nav_Y,
|
||||
Default_Focus_Edit,
|
||||
Focus_Nav_Skip,
|
||||
Disabled,
|
||||
|
||||
// Note(rjf) : Layout
|
||||
Floating_X,
|
||||
Floating_Y,
|
||||
Fixed_Width,
|
||||
Fixed_Height,
|
||||
Allow_Overflow_X,
|
||||
Allow_Overflow_Y,
|
||||
Skip_View_Off_X,
|
||||
Skip_View_Off_Y,
|
||||
|
||||
// Note(rjf) : Appearance / Animation
|
||||
Draw_Drop_Shadow,
|
||||
Draw_Background_Blur,
|
||||
Draw_Background,
|
||||
Draw_Border,
|
||||
Draw_Side_Top,
|
||||
Draw_Side_Bottom,
|
||||
Draw_Side_Left,
|
||||
Draw_Side_Right,
|
||||
Draw_Text,
|
||||
Draw_Text_Fastpath_Codepoint,
|
||||
Draw_Hot_Effects,
|
||||
Draw_Overlay,
|
||||
Draw_Bucket,
|
||||
Clip,
|
||||
Animate_Pos_X,
|
||||
Animate_Pos_Y,
|
||||
Disable_Text_Trunc,
|
||||
Disable_ID_String,
|
||||
Disable_Focus_Viz,
|
||||
Require_Focus_Background,
|
||||
Has_Display_String,
|
||||
Has_Fuzzy_Match_Ranges,
|
||||
Round_Children_By_Parent,
|
||||
|
||||
Count,
|
||||
}
|
||||
UI_BoxFlags :: bit_set[UI_BoxFlag; u64]
|
||||
|
||||
UI_BoxFlags_Null :: UI_BoxFlags {}
|
||||
UI_BoxFlags_Clickable :: UI_BoxFlags { .Mouse_Clickable, .Keyboard_Clickable }
|
||||
|
||||
UI_NullLabel :: ""
|
||||
|
||||
UI_BoxCustomDrawProc :: #type proc( box : ^ UI_Box, user_data : rawptr )
|
||||
|
||||
UI_BoxCustomDraw :: struct {
|
||||
callback : UI_BoxCustomDrawProc,
|
||||
data : rawptr,
|
||||
}
|
||||
|
||||
UI_BoxRec :: struct {
|
||||
next : ^ UI_BoxNode,
|
||||
push_count : i32,
|
||||
pop_count : i32,
|
||||
}
|
||||
|
||||
UI_BoxNode :: struct {
|
||||
next : ^ UI_BoxNode,
|
||||
box : ^ UI_Box,
|
||||
}
|
||||
|
||||
UI_BoxList :: struct {
|
||||
first : UI_BoxNode,
|
||||
last : UI_BoxNode,
|
||||
count : u64,
|
||||
}
|
||||
|
||||
UI_BoxHashSlot :: struct {
|
||||
first, last : ^ UI_Box
|
||||
}
|
||||
|
||||
// Note(Ed) : This is called UI_Widget in the substack series, its called box in raddbg
|
||||
// This eventually gets renamed by part 4 of the series to UI_Box.
|
||||
// However, its essentially a UI_Node or UI_BaselineEntity, etc.
|
||||
// Think of godot's Control nodes I guess.
|
||||
// TODO(Ed) : We dumped all the fields present within raddbg, review which ones are actually needed.
|
||||
UI_Box :: struct {
|
||||
// Note(rjf) : persistent links
|
||||
hash : struct {
|
||||
next, prev : ^ UI_Box,
|
||||
},
|
||||
|
||||
// Note(rjf) : Per-build links & data
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
first, last, prev, next : ^ UI_Box,
|
||||
num_children : i32,
|
||||
|
||||
// Note(rjf) : Key + generation info
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
key : UI_Key,
|
||||
last_frame_touched_index : u64,
|
||||
|
||||
// Note(rjf) : Per-frame info provided by builders
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
flags : UI_BoxFlags,
|
||||
display_str : string, // raddbg: string
|
||||
semantic_size : [Axis2.Count]UI_Size,
|
||||
text_align : UI_TextAlign,
|
||||
fixed_pos : Vec2,
|
||||
fixed_size : Vec2,
|
||||
pref_size : [Axis2.Count]UI_Size,
|
||||
child_layout_axis : Axis2,
|
||||
hover_cursor : OS_Cursor,
|
||||
fastpath_codepoint : u32,
|
||||
draw_bucket : DrawBucket, // TODO(Ed): Translate to equivalent in raylib if necessary
|
||||
custom_draw : UI_BoxCustomDraw,
|
||||
bg_color : Color,
|
||||
text_color : Color,
|
||||
border_color : Color,
|
||||
overlay_color : Color,
|
||||
font : FontID,
|
||||
font_size : f32,
|
||||
corner_radii : [Corner.Count]f32,
|
||||
blur_size : f32, // TODO(Ed) : You would need to run a custom shader with raylib or have your own rendering backend for this.
|
||||
transparency : f32,
|
||||
squish : f32,
|
||||
text_padding : f32,
|
||||
|
||||
// Note(rjf) : Per-frame artifacts by builders
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
display_string_runs : DrawFancyRunList, // TODO(Ed) : Translate to equivalent in raylib if necessary
|
||||
rect : Range2,
|
||||
fixed_pos_animated : Vec2,
|
||||
pos_delta : Vec2,
|
||||
fuzzy_match_range : FuzzyMatchRangeList, // TODO(Ed) : I'm not sure this is needed
|
||||
|
||||
// Note(rjf) : Computed every frame
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
computed_rel_pos : Vec2, // TODO(Ed) : Raddbg doesn't have these, check what they became or if needed
|
||||
computed_size : Vec2,
|
||||
|
||||
// Note(rjf) : Persistent data
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
first_touched_build_id : u64,
|
||||
last_touched_build_id : u64,
|
||||
hot_time : f32,
|
||||
active_time : f32,
|
||||
disabled_time : f32,
|
||||
focus_hot_time : f32,
|
||||
focus_active_time : f32,
|
||||
focus_active_disabled_time : f32,
|
||||
view_off : Vec2,
|
||||
view_off_target : Vec2,
|
||||
view_bounds : Vec2,
|
||||
default_nav_focus_hot_key : UI_Key,
|
||||
default_nav_focus_active_key : UI_Key,
|
||||
default_nav_focus_next_hot_key : UI_Key,
|
||||
default_nav_focus_next_active_key : UI_Key,
|
||||
}
|
76
code/__Imgui_raddbg/ui_state.odin
Normal file
76
code/__Imgui_raddbg/ui_state.odin
Normal file
@ -0,0 +1,76 @@
|
||||
package wip
|
||||
|
||||
import "core:os"
|
||||
|
||||
// TODO(Ed) : As with UI_Box, not all of this will be implemented at once,
|
||||
// we'll need to review this setup for our use case, we will have UI persistent of
|
||||
// a workspace (global state UI), and one for the workspace itself.
|
||||
// The UI state use in raddbg seems to be tied to an OS window and has realted things to it.
|
||||
// You may need to lift the nav actions outside of the UI_State of a workspace, etc...
|
||||
UI_State :: struct {
|
||||
arena : ^ Arena,
|
||||
|
||||
build_arenas : [2] ^ Arena,
|
||||
build_id : u64,
|
||||
|
||||
// Note(rjf) : Box cache
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
first_free_box : UI_Box,
|
||||
box_table_size : u64,
|
||||
box_table : ^ UI_BoxHashSlot, // TODO(Ed) : Can the cache use HashTable?
|
||||
|
||||
// Note(rjf) : Build phase output
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
root : ^ UI_Box,
|
||||
tooltip_root : ^ UI_Box,
|
||||
ctx_menu_root : ^ UI_Box,
|
||||
default_nav_root_key : UI_Key,
|
||||
build_box_count : u64,
|
||||
last_build_box_count : u64,
|
||||
ctx_menu_touched_this_frame : b32,
|
||||
|
||||
// Note(rjf) : Build parameters
|
||||
// icon_info : UI_IconInfo
|
||||
// window : os.Handle
|
||||
// events : OS_EventList
|
||||
nav_actions : UI_NavActionList,
|
||||
// TODO(Ed) : Do we want to keep tracvk of the cursor pos separately
|
||||
// incase we do some sequence for tutorials?
|
||||
mouse : Vec2,
|
||||
animation_delta : f32,
|
||||
external_focus_commit : b32,
|
||||
|
||||
// Note(rjf) : User Interaction State
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
hot_box_key : UI_Key,
|
||||
active_box_key : [Side.Count] UI_Key,
|
||||
clipboard_copy_key : UI_Key,
|
||||
time_since_last_click : [Side.Count] f32,
|
||||
last_click_key : [Side.Count] UI_Key,
|
||||
drag_start_mouse : Vec2,
|
||||
drag_state_arena : ^ Arena,
|
||||
drag_state_data : string,
|
||||
string_hover_arena : ^ Arena,
|
||||
string_hover_string : string,
|
||||
string_hover_fancy_runs : DrawFancyRunList,
|
||||
string_hover_begin_us : u64,
|
||||
string_hover_build_index : u64,
|
||||
last_time_mouse_moved_us : u64,
|
||||
|
||||
// Note(rjf) : Tooltip State
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
tool_tip_open_time : f32,
|
||||
tool_tip_open : b32,
|
||||
|
||||
// Note(rjf) : Context menu state
|
||||
// TODO(ED) : Put this in its own struct?
|
||||
ctx_menu_anchor_key : UI_Key,
|
||||
next_ctx_menu_anchor_key : UI_Key,
|
||||
ctx_menu_anchor_box_last_pos : Vec2,
|
||||
cxt_menu_anchor_off : Vec2,
|
||||
ctx_menu_open : b32,
|
||||
next_ctx_menu_open : b32,
|
||||
ctx_menu_open_time : f32,
|
||||
ctx_menu_key : UI_Key,
|
||||
ctx_menu_changed : b32,
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package sectr
|
||||
|
||||
import "base:runtime"
|
||||
import c "core:c/libc"
|
||||
import "core:dynlib"
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
@ -71,6 +72,8 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^
|
||||
input = & input_data[1]
|
||||
input_prev = & input_data[0]
|
||||
|
||||
// rl.Odin_SetMalloc( RL_MALLOC )
|
||||
|
||||
rl.SetConfigFlags( { rl.ConfigFlag.WINDOW_RESIZABLE /*, rl.ConfigFlag.WINDOW_TOPMOST*/ } )
|
||||
|
||||
// Rough setup of window with rl stuff
|
||||
@ -145,6 +148,8 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^
|
||||
|
||||
frame_2.color = Color_BG_TextBox_Green
|
||||
box_set_size( & frame_2, { 60, 100 } * CM_Per_Point )
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
code/app_startup.odin
Normal file
5
code/app_startup.odin
Normal file
@ -0,0 +1,5 @@
|
||||
package sectr
|
||||
|
||||
|
||||
|
||||
|
@ -132,12 +132,24 @@ AppWindow :: struct {
|
||||
ppcm : f32, // Dots per centimetre
|
||||
}
|
||||
|
||||
// PMDB
|
||||
CodeBase :: struct {
|
||||
placeholder : int,
|
||||
}
|
||||
|
||||
ProjectConfig :: struct {
|
||||
placeholder : int,
|
||||
}
|
||||
|
||||
Project :: struct {
|
||||
path : string,
|
||||
name : string,
|
||||
|
||||
config : ProjectConfig,
|
||||
codebase : CodeBase,
|
||||
|
||||
// TODO(Ed) : Support multiple workspaces
|
||||
workspace : Workspace
|
||||
workspace : Workspace,
|
||||
}
|
||||
|
||||
Workspace :: struct {
|
||||
@ -146,6 +158,9 @@ Workspace :: struct {
|
||||
cam : Camera,
|
||||
frame_1 : Box2,
|
||||
frame_2 : Box2,
|
||||
|
||||
// TODO(Ed) : The workspace is mainly a 'UI' conceptually...
|
||||
ui : UI_State,
|
||||
}
|
||||
|
||||
DebugData :: struct {
|
||||
|
@ -9,7 +9,7 @@ import "core:os"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
Font_Arena_Size :: 32 * Megabyte
|
||||
Font_Largest_Px_Size :: 96
|
||||
Font_Largest_Px_Size :: 32
|
||||
|
||||
// Font_Default :: ""
|
||||
Font_Default :: 0
|
||||
@ -56,6 +56,7 @@ FontProviderData :: struct {
|
||||
|
||||
//TODO(Ed) : There is an issue with hot-reload and map allocations that I can't figure out right now..
|
||||
// font_cache : ^ map [FontID](FontDef),
|
||||
// font_cache : HashTable(FontDef),
|
||||
font_cache : [10] FontDef,
|
||||
open_id : i32
|
||||
}
|
||||
|
101
code/grime.odin
101
code/grime.odin
@ -3,8 +3,11 @@ package sectr
|
||||
// At least its less than C/C++ ...
|
||||
|
||||
import "base:builtin"
|
||||
import "base:runtime"
|
||||
import c "core:c/libc"
|
||||
import "core:mem"
|
||||
import "core:mem/virtual"
|
||||
import "core:os"
|
||||
import "core:path/filepath"
|
||||
|
||||
Byte :: 1
|
||||
@ -49,3 +52,101 @@ get_bounds :: proc {
|
||||
box_get_bounds,
|
||||
view_get_bounds,
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO(Ed) : This is extremely jank, Raylib requires a 'heap' allocator with the way it works.
|
||||
// We do not have persistent segmented in such a way for this. Eventually we might just want to segment vmem and just shove a heap allocator on a segment of it.
|
||||
|
||||
when false {
|
||||
RL_MALLOC :: proc "c" ( size : c.size_t ) -> rawptr
|
||||
{
|
||||
allocator : Allocator
|
||||
when Use_TrackingAllocator {
|
||||
allocator = Allocator {
|
||||
data = & memory.persistent.tracker,
|
||||
procedure = mem.tracking_allocator_proc,
|
||||
}
|
||||
}
|
||||
else {
|
||||
allocator = Allocator {
|
||||
data = & memory.persistent,
|
||||
procedure = mem.arena_allocator_proc,
|
||||
}
|
||||
}
|
||||
result, error_code := allocator.procedure( allocator.data, mem.Allocator_Mode.Alloc_Non_Zeroed, cast(int) size, mem.DEFAULT_ALIGNMENT, nil, 0, auto_cast {} )
|
||||
if error_code != AllocatorError.None {
|
||||
runtime.debug_trap()
|
||||
os.exit( -1 )
|
||||
}
|
||||
return raw_data(result)
|
||||
}
|
||||
|
||||
RL_CALLOC :: proc "c" ( count : c.size_t, size : c.size_t ) -> rawptr
|
||||
{
|
||||
allocator : Allocator
|
||||
when Use_TrackingAllocator {
|
||||
allocator = Allocator {
|
||||
data = & memory.persistent.tracker,
|
||||
procedure = mem.tracking_allocator_proc,
|
||||
}
|
||||
}
|
||||
else {
|
||||
allocator = Allocator {
|
||||
data = & memory.persistent,
|
||||
procedure = mem.arena_allocator_proc,
|
||||
}
|
||||
}
|
||||
result, error_code := allocator.procedure( allocator.data, mem.Allocator_Mode.Alloc, cast(int) size, mem.DEFAULT_ALIGNMENT, nil, 0, auto_cast {} )
|
||||
if error_code != AllocatorError.None {
|
||||
runtime.debug_trap()
|
||||
os.exit( -1 )
|
||||
}
|
||||
return raw_data(result)
|
||||
}
|
||||
|
||||
RL_REALLOC :: proc "c" ( block : rawptr, size : c.size_t ) -> rawptr
|
||||
{
|
||||
allocator : Allocator
|
||||
when Use_TrackingAllocator {
|
||||
allocator = Allocator {
|
||||
data = & memory.persistent.tracker,
|
||||
procedure = mem.tracking_allocator_proc,
|
||||
}
|
||||
}
|
||||
else {
|
||||
allocator = Allocator {
|
||||
data = & memory.persistent,
|
||||
procedure = mem.arena_allocator_proc,
|
||||
}
|
||||
}
|
||||
result, error_code := allocator.procedure( allocator.data, mem.Allocator_Mode.Resize_Non_Zeroed, cast(int) size, mem.DEFAULT_ALIGNMENT, block, 0, auto_cast {} )
|
||||
if error_code != AllocatorError.None {
|
||||
runtime.debug_trap()
|
||||
os.exit( -1 )
|
||||
}
|
||||
return raw_data(result)
|
||||
}
|
||||
|
||||
RL_FREE :: proc "c" ( block : rawptr )
|
||||
{
|
||||
allocator : Allocator
|
||||
when Use_TrackingAllocator {
|
||||
allocator = Allocator {
|
||||
data = & memory.persistent.tracker,
|
||||
procedure = mem.tracking_allocator_proc,
|
||||
}
|
||||
}
|
||||
else {
|
||||
allocator = Allocator {
|
||||
data = & memory.persistent,
|
||||
procedure = mem.arena_allocator_proc,
|
||||
}
|
||||
}
|
||||
result, error_code := allocator.procedure( allocator.data, mem.Allocator_Mode.Free, 0, 0, block, 0, auto_cast {} )
|
||||
if error_code != AllocatorError.None {
|
||||
runtime.debug_trap()
|
||||
os.exit( -1 )
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
// with hot-reloads...
|
||||
package sectr
|
||||
|
||||
// Note(Ed) : See core:hash for hasing procs.
|
||||
|
||||
// This might be problematic...
|
||||
HT_MapProc :: #type proc( $ Type : typeid, key : u64, value : Type )
|
||||
HT_MapMutProc :: #type proc( $ Type : typeid, key : u64, value : ^ Type )
|
||||
|
@ -129,3 +129,14 @@ arena_init_static :: proc(arena: ^virtual.Arena, base_address : rawptr,
|
||||
|
||||
// END WINDOWS CHECK WRAP
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback to regular init_static impl for other platforms for now.
|
||||
|
||||
arena_init_static :: proc(arena: ^virtual.Arena, base_address : rawptr,
|
||||
reserved : uint = virtual.DEFAULT_ARENA_STATIC_RESERVE_SIZE,
|
||||
commit_size : uint = virtual.DEFAULT_ARENA_STATIC_COMMIT_SIZE
|
||||
) -> (err: virtual.Allocator_Error) {
|
||||
return virtual.arena_init_static( arena, reserved, commit_size )
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package sectr
|
||||
|
||||
import rl "vendor:raylib"
|
||||
|
||||
// TODO(Ed) : Do we want to have distinct types for cm/pixels/points ? This will make mistakes with unit conversion happen less.
|
||||
|
||||
// The points to pixels and pixels to points are our only reference to accurately converting
|
||||
// an object from world space to screen-space.
|
||||
// This prototype engine will have all its spacial unit base for distances in centimetres.
|
||||
@ -16,7 +18,7 @@ DPT_PPCM :: cast(f32) 96.0 * Inches_To_CM // 243.84 pixels per cm
|
||||
when ODIN_OS == OS_Type.Windows {
|
||||
op_default_dpcm :: 72.0 * Inches_To_CM
|
||||
os_default_ppcm :: 96.0 * Inches_To_CM
|
||||
// 1 inch = 2.54 cm, 96 inch * 2.54 = 243.84 DPC
|
||||
// 1 inch = 2.54 cm, 96 inch * 2.54 = 243.84 DPCM
|
||||
}
|
||||
|
||||
cm_to_pixels :: proc {
|
||||
|
@ -19,7 +19,7 @@ render :: proc()
|
||||
rl.BeginDrawing()
|
||||
rl.ClearBackground( Color_BG )
|
||||
render_mode_2d()
|
||||
// Render Screenspace
|
||||
//region Render Screenspace
|
||||
{
|
||||
fps_msg := fmt.tprint( "FPS:", rl.GetFPS() )
|
||||
fps_msg_width := measure_text_size( fps_msg, default_font, 16.0, 0.0 ).x
|
||||
@ -68,6 +68,7 @@ render :: proc()
|
||||
|
||||
debug.draw_debug_text_y = 50
|
||||
}
|
||||
//endregion Render Screenspace
|
||||
rl.EndDrawing()
|
||||
}
|
||||
|
||||
@ -79,27 +80,11 @@ render_mode_2d :: proc()
|
||||
|
||||
rl.BeginMode2D( project.workspace.cam )
|
||||
|
||||
// debug.frame_1_on_top = true
|
||||
//region Imgui Render
|
||||
{
|
||||
|
||||
boxes : [2]^Box2
|
||||
if debug.frame_1_on_top {
|
||||
boxes = { & project.workspace.frame_2, & project.workspace.frame_1 }
|
||||
}
|
||||
else {
|
||||
boxes = { & project.workspace.frame_1, & project.workspace.frame_2 }
|
||||
}
|
||||
|
||||
for box in boxes {
|
||||
screen_pos := world_to_screen_no_zoom(box.position) - vec2_cm_to_pixels( Vec2(box.extent) )
|
||||
size := vec2_cm_to_pixels( transmute(Vec2) box.extent * 2.0 )
|
||||
|
||||
rect : rl.Rectangle
|
||||
rect.x = screen_pos.x
|
||||
rect.y = screen_pos.y
|
||||
rect.width = size.x
|
||||
rect.height = size.y
|
||||
rl.DrawRectangleRec( rect, box.color )
|
||||
}
|
||||
//endregion Imgui Render
|
||||
|
||||
debug_draw_text_world( "This is text in world space", { 0, 0 }, 16.0 )
|
||||
|
||||
|
@ -86,7 +86,7 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
}
|
||||
}
|
||||
|
||||
// Input Replay
|
||||
//region Input Replay
|
||||
{
|
||||
if debug_actions.record_replay { #partial switch replay.mode
|
||||
{
|
||||
@ -129,27 +129,28 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
play_input( replay.active_file, input )
|
||||
}
|
||||
}
|
||||
//endregion Input Replay
|
||||
|
||||
if debug_actions.show_mouse_pos {
|
||||
debug.mouse_vis = !debug.mouse_vis
|
||||
}
|
||||
|
||||
// Camera Manual Nav
|
||||
//region Camera Manual Nav
|
||||
{
|
||||
cam := & project.workspace.cam
|
||||
|
||||
digital_move_speed : f32 = 200.0
|
||||
zoom_sensitivity : f32 = 0.2 // Digital
|
||||
// zoom_sensitivity : f32 = 2.0 // Smooth
|
||||
// zoom_sensitivity : f32 = 0.2 // Digital
|
||||
zoom_sensitivity : f32 = 4.0 // Smooth
|
||||
|
||||
if debug.zoom_target == 0.0 {
|
||||
debug.zoom_target = cam.zoom
|
||||
}
|
||||
|
||||
// Adjust zoom_target based on input, not the actual zoom
|
||||
zoom_delta := input.mouse.vertical_wheel * zoom_sensitivity
|
||||
debug.zoom_target *= 1 + zoom_delta //* f32(delta_time)
|
||||
debug.zoom_target = clamp(debug.zoom_target, 0.25, 10.0)
|
||||
// Adjust zoom_target based on input, not the actual zoom
|
||||
zoom_delta := input.mouse.vertical_wheel * zoom_sensitivity
|
||||
debug.zoom_target *= 1 + zoom_delta * f32(delta_time)
|
||||
debug.zoom_target = clamp(debug.zoom_target, 0.25, 10.0)
|
||||
|
||||
// Linearly interpolate cam.zoom towards zoom_target
|
||||
lerp_factor := cast(f32) 4.0 // Adjust this value to control the interpolation speed
|
||||
@ -171,32 +172,14 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
}
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
boxes : [2]^Box2
|
||||
boxes = { & project.workspace.frame_1, & project.workspace.frame_2 }
|
||||
if debug.frame_1_on_top {
|
||||
boxes = { & project.workspace.frame_2, & project.workspace.frame_1 }
|
||||
}
|
||||
else {
|
||||
boxes = { & project.workspace.frame_1, & project.workspace.frame_2 }
|
||||
}
|
||||
|
||||
if debug_actions.mouse_select
|
||||
//region Imgui Tick
|
||||
{
|
||||
for box in boxes
|
||||
{
|
||||
cursor_pos := screen_to_world( input.mouse.pos )
|
||||
if box_is_within( box, cursor_pos )
|
||||
{
|
||||
if box == & project.workspace.frame_1 {
|
||||
debug.frame_1_on_top = true
|
||||
}
|
||||
else {
|
||||
debug.frame_1_on_top = false
|
||||
}
|
||||
}
|
||||
}
|
||||
// Layout
|
||||
|
||||
}
|
||||
// endregion
|
||||
|
||||
debug.last_mouse_pos = input.mouse.pos
|
||||
|
||||
|
404
code/ui.odin
404
code/ui.odin
@ -1,272 +1,208 @@
|
||||
package sectr
|
||||
|
||||
// Based off Ryan Fleury's UI Series & Epic's RAD Debugger which directly implements a version of it.
|
||||
// You will see Note(rjf) these are comments directly from the RAD Debugger codebase by Fleury.
|
||||
// TODO(Ed) If I can, I would like this to be its own package, but the nature of packages in odin may make this difficult.
|
||||
|
||||
// TODO(Ed) : This is in Raddbg base_types.h, consider moving outside of UI.
|
||||
Axis2 :: enum {
|
||||
Invalid = -1,
|
||||
X,
|
||||
Y,
|
||||
Axis2 :: enum i32 {
|
||||
Invalid = -1,
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_FocusKind :: enum u32 {
|
||||
Null,
|
||||
Off,
|
||||
On,
|
||||
Root,
|
||||
Corner :: enum i32 {
|
||||
Invalid = -1,
|
||||
_00,
|
||||
_01,
|
||||
_10,
|
||||
_11,
|
||||
TopLeft = _00,
|
||||
TopRight = _01,
|
||||
BottomLeft = _10,
|
||||
BottomRight = _11,
|
||||
Count = 4,
|
||||
}
|
||||
|
||||
Range2 :: struct #raw_union{
|
||||
using _ : struct {
|
||||
min, max : Vec2
|
||||
},
|
||||
using _ : struct {
|
||||
p0, p1 : Vec2
|
||||
},
|
||||
using _ : struct {
|
||||
x0, y0 : f32,
|
||||
x1, y1 : f32,
|
||||
},
|
||||
}
|
||||
|
||||
Rect :: struct {
|
||||
top_left, bottom_right : Vec2
|
||||
}
|
||||
|
||||
Side :: enum i32 {
|
||||
Invalid = -1,
|
||||
Min = 0,
|
||||
Max = 1,
|
||||
Count
|
||||
}
|
||||
|
||||
// Side2 :: enum u32 {
|
||||
// Top,
|
||||
// Bottom,
|
||||
// Left,
|
||||
// Right,
|
||||
// Count,
|
||||
// }
|
||||
|
||||
UI_AnchorPresets :: enum u32 {
|
||||
Top_Left,
|
||||
Top_Right,
|
||||
Bottom_Right,
|
||||
Bottom_Left,
|
||||
Center_Left,
|
||||
Center_Top,
|
||||
Center_Right,
|
||||
Center_Bottom,
|
||||
Center,
|
||||
Left_Wide,
|
||||
Top_Wide,
|
||||
Right_Wide,
|
||||
Bottom_Wide,
|
||||
VCenter_Wide,
|
||||
HCenter_Wide,
|
||||
Full,
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_IconKind :: enum u32 {
|
||||
Null,
|
||||
Arrow_Up,
|
||||
Arrow_Left,
|
||||
Arrow_Right,
|
||||
Arrow_Down,
|
||||
Caret_Up,
|
||||
Caret_Left,
|
||||
Caret_Right,
|
||||
Caret_Down,
|
||||
Check_Hollow,
|
||||
Check_Filled,
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_IconInfo :: struct {
|
||||
placehodler : int
|
||||
}
|
||||
|
||||
UI_NavDeltaUnit :: enum u32 {
|
||||
Element,
|
||||
Chunk,
|
||||
Whole,
|
||||
End_Point,
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_NavActionFlag :: enum u32 {
|
||||
Keep_Mark,
|
||||
Delete,
|
||||
Copy,
|
||||
Paste,
|
||||
Zero_Delta_On_Select,
|
||||
Pick_Select_Side,
|
||||
Can_At_Line,
|
||||
Explicit_Directional,
|
||||
Replace_And_Commit,
|
||||
}
|
||||
UI_NavActionFlags :: bit_set[UI_NavActionFlag; u32]
|
||||
|
||||
UI_NavAction :: struct {
|
||||
flags : UI_NavActionFlags,
|
||||
delta : Vec2i,
|
||||
delta_unit : UI_NavDeltaUnit,
|
||||
insertion : string,
|
||||
}
|
||||
|
||||
UI_SizeKind :: enum u32 {
|
||||
Null,
|
||||
Pixels,
|
||||
Points,
|
||||
TextContent,
|
||||
PercentOfParent,
|
||||
ChildrenSum,
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_Size :: struct {
|
||||
kind : UI_SizeKind,
|
||||
value : f32,
|
||||
strictness : f32,
|
||||
}
|
||||
|
||||
UI_Size2 : struct {
|
||||
kind : [Axis2.Count]UI_SizeKind,
|
||||
value : Vec2,
|
||||
strictness : Vec2,
|
||||
}
|
||||
|
||||
UI_Layout :: struct {
|
||||
placeholder : int
|
||||
}
|
||||
|
||||
UI_Key :: struct {
|
||||
opaque : [1]u64,
|
||||
}
|
||||
|
||||
UI_BoxFlag :: enum u64 {
|
||||
// Note(rjf) : Interaction
|
||||
Focusable,
|
||||
|
||||
Mouse_Clickable,
|
||||
Keyboard_Clickable,
|
||||
Click_To_Focus,
|
||||
Scroll,
|
||||
View_Scroll_X,
|
||||
View_Scroll_Y,
|
||||
View_Clamp_X,
|
||||
View_Clamp_Y,
|
||||
Focus_Active,
|
||||
Focus_Active_Disabled,
|
||||
Focus_Hot,
|
||||
Focus_Hot_Disabled,
|
||||
Default_Focus_Nav_X,
|
||||
Default_Focus_Nav_Y,
|
||||
Default_Focus_Edit,
|
||||
Focus_Nav_Skip,
|
||||
Disabled,
|
||||
|
||||
// Note(rjf) : Layout
|
||||
Floating_X,
|
||||
Floating_Y,
|
||||
Fixed_Width,
|
||||
Fixed_With,
|
||||
Fixed_Height,
|
||||
Allow_Overflow_X,
|
||||
Allow_Overflow_Y,
|
||||
Skip_View_Off_X,
|
||||
Skip_View_Off_Y,
|
||||
|
||||
// Note(rjf) : Appearance / Animation
|
||||
Draw_Drop_Shadow,
|
||||
Draw_Background_Blur,
|
||||
Draw_Background,
|
||||
Draw_Border,
|
||||
Draw_Side_Top,
|
||||
Draw_Side_Bottom,
|
||||
Draw_Side_Left,
|
||||
Draw_Side_Right,
|
||||
Draw_Text,
|
||||
Draw_Text_Fastpath_Codepoint,
|
||||
Draw_Hot_Effects,
|
||||
Draw_Overlay,
|
||||
Draw_Bucket,
|
||||
Clip,
|
||||
Animate_Pos_X,
|
||||
Animate_Pos_Y,
|
||||
Disable_Text_Trunc,
|
||||
Disable_ID_String,
|
||||
Disable_Focus_Viz,
|
||||
Require_Focus_Background,
|
||||
Has_Display_String,
|
||||
Has_Fuzzy_Match_Ranges,
|
||||
Round_Children_By_Parent,
|
||||
Text_Wrap,
|
||||
|
||||
Count,
|
||||
}
|
||||
UI_BoxFlags :: bit_set[UI_BoxFlag; u64]
|
||||
|
||||
UI_BoxFlags_Null :: UI_BoxFlags {}
|
||||
UI_BoxFlags_Clickable :: UI_BoxFlags { .Mouse_Clickable, .Keyboard_Clickable }
|
||||
// The UI_Box's actual positioning and sizing
|
||||
// There is an excess of rectangles here for debug puproses.
|
||||
UI_Computed :: struct {
|
||||
bounds : Range2,
|
||||
border : Range2,
|
||||
margin : Range2,
|
||||
padding : Range2,
|
||||
content : Range2,
|
||||
}
|
||||
|
||||
UI_NullLabel :: ""
|
||||
UI_LayoutSide :: struct #raw_union {
|
||||
using _ : struct {
|
||||
top, bottom : UI_Scalar2,
|
||||
left, right : UI_Scalar2,
|
||||
}
|
||||
}
|
||||
|
||||
UI_Cursor :: struct {
|
||||
placeholder : int,
|
||||
}
|
||||
|
||||
UI_Key :: distinct u64
|
||||
|
||||
UI_Scalar :: f32
|
||||
|
||||
// TODO(Ed): I'm not sure if Percentage is needed or if this would over complicate things...
|
||||
// UI_Scalar :: struct {
|
||||
// VPixels : f32,
|
||||
// Percentage : f32,
|
||||
// }
|
||||
|
||||
UI_ScalarConstraint :: struct {
|
||||
min, max : UI_Scalar,
|
||||
}
|
||||
|
||||
UI_Scalar2 :: [Axis2.Count]UI_Scalar
|
||||
|
||||
// Desiered constraints on the UI_Box.
|
||||
UI_Layout :: struct {
|
||||
// TODO(Ed) : Make sure this is all we need to represent an anchor.
|
||||
anchor : Range2,
|
||||
|
||||
border_width : UI_Scalar,
|
||||
|
||||
margins : UI_LayoutSide,
|
||||
padding : UI_LayoutSide,
|
||||
|
||||
corner_radii : [Corner.Count]f32,
|
||||
|
||||
size : UI_ScalarConstraint,
|
||||
}
|
||||
|
||||
UI_Style :: struct {
|
||||
bg_color : Color,
|
||||
overlay_color : Color,
|
||||
border_color : Color,
|
||||
|
||||
// blur_size : f32,
|
||||
|
||||
font : FontID,
|
||||
font_size : f32,
|
||||
text_color : Color,
|
||||
text_alignment : UI_TextAlign,
|
||||
// text_wrap_width_pixels : f32,
|
||||
// text_wrap_width_percent : f32,
|
||||
|
||||
// cursors : [CursorKind.Count]UI_Cursor,
|
||||
// active_cursor : ^UI_Cursor,
|
||||
// hover_cursor : ^ UI_Cursor,
|
||||
}
|
||||
|
||||
UI_TextAlign :: enum u32 {
|
||||
Left,
|
||||
Center,
|
||||
Right,
|
||||
Count
|
||||
}
|
||||
|
||||
// Note(Ed) : This is called UI_Widget in the substack series, its called box in raddbg
|
||||
// This eventually gets renamed by part 4 of the series to UI_Box.
|
||||
// However, its essentially a UI_Node or UI_BaselineEntity, etc.
|
||||
// Think of godot's Control nodes I guess.
|
||||
UI_Box :: struct {
|
||||
// Note(rjf) : persistent links
|
||||
hash : struct {
|
||||
next, prev : ^ UI_Box,
|
||||
},
|
||||
|
||||
// Note(rjf) : Per-build links & data
|
||||
first, last, prev, next : ^ UI_Box,
|
||||
num_children : i32,
|
||||
|
||||
// Note(rjf) : Key + generation info
|
||||
key : UI_Key,
|
||||
last_frame_touched_index : u64,
|
||||
|
||||
// Note(rjf) : Per-frame info provided by builders
|
||||
flags : UI_BoxFlags,
|
||||
display_str : string,
|
||||
semantic_size : [Axis2.Count]UI_Size,
|
||||
|
||||
key : UI_Key,
|
||||
label : string,
|
||||
|
||||
// Note(rjf) : Computed every frame
|
||||
computed_rel_pos : Vec2,
|
||||
computed_size : Vec2,
|
||||
//rect : Rng2F32
|
||||
computed : UI_Computed,
|
||||
|
||||
// Note(rjf) : Persistent data
|
||||
hot : f32,
|
||||
active : f32,
|
||||
layout : UI_Layout,
|
||||
style : UI_Style,
|
||||
|
||||
// bg_color : Color,
|
||||
// txt_color : Color,
|
||||
// Persistent Data
|
||||
hot_time : f32,
|
||||
active_time : f32,
|
||||
disabled_time : f32,
|
||||
}
|
||||
|
||||
UI_Signal :: struct {
|
||||
box : UI_Box,
|
||||
cursor_pos : Vec2,
|
||||
drag_delta : Vec2,
|
||||
scroll : Vec2,
|
||||
left_clicked : b8,
|
||||
right_clicked : b8,
|
||||
double_clicked : b8,
|
||||
keyboard_clicked : b8,
|
||||
pressed : b8,
|
||||
released : b8,
|
||||
dragging : b8,
|
||||
hovering : b8,
|
||||
mouse_over : b8,
|
||||
commit : b8,
|
||||
UI_State :: struct {
|
||||
box_cache : HashTable( UI_Box ),
|
||||
|
||||
box_tree_dirty : b32,
|
||||
root : ^ UI_Box,
|
||||
|
||||
hot : UI_Key,
|
||||
active : UI_Key,
|
||||
clipboard_copy_key : UI_Key,
|
||||
|
||||
drag_start_mouse : Vec2,
|
||||
// drag_state_arena : ^ Arena,
|
||||
// drag_state data : string,
|
||||
}
|
||||
|
||||
ui_key_null :: proc() -> UI_Key {
|
||||
return {}
|
||||
}
|
||||
|
||||
ui_key_from_string :: proc( value : string ) -> UI_Key {
|
||||
return {}
|
||||
}
|
||||
|
||||
ui_key_match :: proc( a, b : UI_Key ) -> b32 {
|
||||
return false
|
||||
}
|
||||
|
||||
ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box) {
|
||||
ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
ui_box_equip_display_string :: proc( box : ^ UI_Box, display_string : string ) {
|
||||
|
||||
}
|
||||
|
||||
ui_box_equip_child_layout_axis :: proc( box : ^ UI_Box, axis : Axis2 ) {
|
||||
|
||||
}
|
||||
|
||||
ui_push_parent :: proc( box : ^ UI_Box ) -> (^ UI_Box) {
|
||||
return nil
|
||||
}
|
||||
|
||||
ui_pop_parent :: proc() -> (^ UI_Box) {
|
||||
return nil
|
||||
}
|
||||
|
||||
ui_signal_from_box :: proc( box : ^ UI_Box ) -> UI_Signal {
|
||||
return {}
|
||||
}
|
||||
|
||||
ui_button :: proc( label : string ) -> UI_Signal {
|
||||
button_flags : UI_BoxFlags =
|
||||
UI_BoxFlags_Clickable & {
|
||||
.Draw_Border,
|
||||
.Draw_Text,
|
||||
.Draw_Background,
|
||||
.Focus_Hot,
|
||||
.Focus_Active,
|
||||
}
|
||||
box := ui_box_make( button_flags, label )
|
||||
signal := ui_signal_from_box( box )
|
||||
return signal
|
||||
}
|
||||
|
||||
ui_spacer :: proc ( label : string = UI_NullLabel ) -> UI_Signal {
|
||||
box := ui_box_make( UI_BoxFlags_Null, label )
|
||||
signal := ui_signal_from_box( box )
|
||||
return signal
|
||||
}
|
||||
|
5
code/ui_proto.odin
Normal file
5
code/ui_proto.odin
Normal file
@ -0,0 +1,5 @@
|
||||
package sectr
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user