Starting to layout scaffolding for UI based on RAD Debugger/Ryan's UI Series
This commit is contained in:
parent
794852a0b0
commit
f36b05e795
@ -91,7 +91,11 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^
|
||||
{
|
||||
path_rec_mono_semicasual_reg := strings.concatenate( { Path_Assets, "RecMonoSemicasual-Regular-1.084.ttf" })
|
||||
cstr := strings.clone_to_cstring( path_rec_mono_semicasual_reg )
|
||||
font_rec_mono_semicasual_reg = rl.LoadFontEx( cstr, 24, nil, 0 )
|
||||
|
||||
font_data, read_succeded : = os.read_entire_file( path_rec_mono_semicasual_reg )
|
||||
verify( ! read_succeded, fmt.tprintf("Failed to read font file for: %v", path_rec_mono_semicasual_reg) )
|
||||
|
||||
font_rec_mono_semicasual_reg = rl.LoadFontEx( cstr, cast(i32) points_to_pixels(24.0), nil, 0 )
|
||||
delete( cstr)
|
||||
|
||||
rl.GuiSetFont( font_rec_mono_semicasual_reg ) // TODO(Ed) : Does this do anything?
|
||||
@ -99,6 +103,7 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^
|
||||
log( "Default font loaded" )
|
||||
}
|
||||
|
||||
// Demo project setup
|
||||
{
|
||||
using project
|
||||
path = "./"
|
||||
@ -122,10 +127,10 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^
|
||||
|
||||
frame_1.color = Color_BG_TextBox
|
||||
// Frame is getting interpreted as points (It doesn't have to be, I'm just doing it...)
|
||||
box_set_size( & frame_1, { 400, 200 } )
|
||||
box_set_size( & frame_1, { 50, 25 } * CM_Per_Point )
|
||||
|
||||
frame_2.color = Color_BG_TextBox_Green
|
||||
box_set_size( & frame_2, { 350, 500 } )
|
||||
box_set_size( & frame_2, { 30, 50 } * CM_Per_Point )
|
||||
// frame_1.position = { 1000, 1000 }
|
||||
}
|
||||
}
|
||||
|
@ -29,11 +29,12 @@ box_is_within_view :: proc( box : ^ Box2 ) -> b32
|
||||
}
|
||||
|
||||
screen_bounds := view_get_bounds()
|
||||
box_bounds := box_get_bounds( box )
|
||||
bounds := box_get_bounds( box )
|
||||
|
||||
within_bounds : b32 = false
|
||||
|
||||
// TODO(Ed) : Should be easy to finish given the other impl...
|
||||
// within_x_bounds : b32 = pos.x >= bounds.top_left.x && pos.x <= bounds.bottom_right.x
|
||||
// within_y_bounds : b32 = pos.y >= bounds.bottom_right.y && pos.y <= bounds.top_left.y
|
||||
|
||||
return within_bounds
|
||||
}
|
||||
|
@ -4,10 +4,15 @@ import "core:encoding/json"
|
||||
|
||||
import rl "vendor:raylib"
|
||||
|
||||
// TODO(Ed) : I made this before doing Ryan's UI series. It was my initial attempt at a "frame"
|
||||
// conceptually that I need as an Entity primitive for all my 2D primitives that I would lay out
|
||||
// in either world (workspace) space or in screenspace (fixed ui space)
|
||||
|
||||
Box2 :: struct {
|
||||
position : Vec2,
|
||||
extent : Extents2,
|
||||
color : Color
|
||||
color : Color,
|
||||
layer : i32,
|
||||
}
|
||||
|
||||
box_size :: proc( box : ^ Box2 ) -> AreaSize {
|
||||
|
@ -22,7 +22,7 @@ pressed :: proc {
|
||||
}
|
||||
|
||||
MaxKeyboardKeys :: 256
|
||||
KeyboardKey :: enum {
|
||||
KeyboardKey :: enum u32 {
|
||||
null = 0x00,
|
||||
|
||||
enter = 0x01,
|
||||
@ -249,7 +249,7 @@ KeyboardState :: struct #raw_union {
|
||||
}
|
||||
|
||||
MaxMouseBtns :: 16
|
||||
MouseBtn :: enum {
|
||||
MouseBtn :: enum u32 {
|
||||
Left = 0x0,
|
||||
Middle = 0x1,
|
||||
Right = 0x2,
|
||||
|
162
code/space.odin
162
code/space.odin
@ -6,130 +6,182 @@ import rl "vendor:raylib"
|
||||
// an object from world space to screen-space.
|
||||
// This prototype engine will have all its spacial unit base for distances in centimetres.
|
||||
|
||||
Inches_To_Centimetre :: cast(f32) 2.54
|
||||
Points_Per_Centimetre := cast(f32) 28.3465
|
||||
Centimetres_Per_Point :: cast(f32) 1.0 / 28.3465 // Precalculated reciprocal for multiplication
|
||||
DPT_DPC :: cast(f32) 72.0 * Inches_To_Centimetre
|
||||
Inches_To_CM :: cast(f32)2.54
|
||||
Points_Per_CM :: cast(f32)28.3465
|
||||
CM_Per_Point :: cast(f32)1.0 / 28.3465 // Precalculated reciprocal for multiplication
|
||||
DPT_DPC :: cast(f32)72.0 * Inches_To_CM
|
||||
|
||||
when ODIN_OS == OS_Type.Windows {
|
||||
os_default_dpc :: 96 * Inches_To_Centimetre
|
||||
os_default_dpc :: 96 * Inches_To_CM
|
||||
// 1 inch = 2.54 cm, 96 inch * 2.54 = 243.84 DPC
|
||||
}
|
||||
|
||||
// points_to_cm :: proc( points : f32 ) -> f32 {
|
||||
// return points *
|
||||
cm_to_pixels :: proc {
|
||||
f32_cm_to_pixels,
|
||||
vec2_cm_to_pixels,
|
||||
}
|
||||
|
||||
pixels_to_cm :: proc {
|
||||
f32_pixels_to_cm,
|
||||
vec2_pixels_to_cm,
|
||||
}
|
||||
|
||||
points_to_pixels :: proc {
|
||||
f32_points_to_pixels,
|
||||
vec2_points_to_pixels,
|
||||
}
|
||||
|
||||
|
||||
//region Unit Conversion Impl
|
||||
|
||||
// cm_to_points :: proc ( cm : f32 ) -> f32 {
|
||||
|
||||
// }
|
||||
|
||||
cm_to_pixels :: proc( cm : f32 ) -> f32 {
|
||||
// points_to_cm :: proc( points : f32 ) -> f32 {
|
||||
// screen_dpc := get_state().app_window.dpc
|
||||
// cm_per_pixel := 1.0 / screen_dpc
|
||||
// pixels := points * DPT_DPC * cm_per_pixel
|
||||
// return points *
|
||||
// }
|
||||
|
||||
f32_cm_to_pixels :: proc(cm: f32) -> f32 {
|
||||
screen_dpc := get_state().app_window.dpc
|
||||
return cm * screen_dpc
|
||||
}
|
||||
|
||||
vec2_cm_to_pixels :: proc( v : Vec2 ) -> Vec2 {
|
||||
f32_pixels_to_cm :: proc(pixels: f32) -> f32 {
|
||||
screen_dpc := get_state().app_window.dpc
|
||||
return v * screen_dpc
|
||||
cm_per_pixel := 1.0 / screen_dpc
|
||||
return pixels * cm_per_pixel
|
||||
}
|
||||
|
||||
points_to_pixels :: proc( points : f32 ) -> f32 {
|
||||
f32_points_to_pixels :: proc(points: f32) -> f32 {
|
||||
screen_dpc := get_state().app_window.dpc
|
||||
cm_per_pixel := 1.0 / screen_dpc
|
||||
return points * DPT_DPC * cm_per_pixel
|
||||
}
|
||||
|
||||
pixels_to_points :: proc( pixels : f32 ) -> f32 {
|
||||
f32_pixels_to_points :: proc(pixels: f32) -> f32 {
|
||||
screen_dpc := get_state().app_window.dpc
|
||||
cm_per_pixel := 1.0 / screen_dpc
|
||||
return pixels * cm_per_pixel * Points_Per_Centimetre
|
||||
return pixels * cm_per_pixel * Points_Per_CM
|
||||
}
|
||||
|
||||
vec2_points_to_pixels :: proc ( vpoints : Vec2 ) -> Vec2 {
|
||||
vec2_cm_to_pixels :: proc(v: Vec2) -> Vec2 {
|
||||
screen_dpc := get_state().app_window.dpc
|
||||
return v * screen_dpc
|
||||
}
|
||||
|
||||
vec2_pixels_to_cm :: proc(v: Vec2) -> Vec2 {
|
||||
screen_dpc := get_state().app_window.dpc
|
||||
cm_per_pixel := 1.0 / screen_dpc
|
||||
return v * cm_per_pixel
|
||||
}
|
||||
|
||||
vec2_points_to_pixels :: proc(vpoints: Vec2) -> Vec2 {
|
||||
screen_dpc := get_state().app_window.dpc
|
||||
cm_per_pixel := 1.0 / screen_dpc
|
||||
return vpoints * DPT_DPC * cm_per_pixel
|
||||
}
|
||||
|
||||
|
||||
// vec2_points_to_cm :: proc ( vpoints : Vec2 ) -> Vec2 {
|
||||
|
||||
// }
|
||||
|
||||
//endregion
|
||||
|
||||
Camera :: rl.Camera2D
|
||||
|
||||
// TODO(Ed) : I'm not sure making the size and extent types distinct has made things easier or more difficult in Odin..
|
||||
// The lack of operator overloads is going to make any sort of nice typesystem
|
||||
// for doing lots of math or phyiscs more error prone or filled with proc wrappers
|
||||
AreaSize :: distinct Vec2
|
||||
|
||||
Bounds2 :: struct {
|
||||
top_left, bottom_right : Vec2
|
||||
top_left, bottom_right: Vec2,
|
||||
}
|
||||
|
||||
BoundsCorners2 :: struct {
|
||||
top_left, top_right, bottom_left, bottom_right : Vec2
|
||||
top_left, top_right, bottom_left, bottom_right: Vec2,
|
||||
}
|
||||
|
||||
Extents2 :: distinct Vec2
|
||||
Extents2 :: distinct Vec2
|
||||
Extents2i :: distinct Vec2i
|
||||
|
||||
bounds2_radius :: proc( bounds : Bounds2 ) -> f32 {
|
||||
return max( bounds.bottom_right.x, bounds.top_left.y )
|
||||
WS_Pos :: struct {
|
||||
tile_id : Vec2i,
|
||||
rel : Vec2,
|
||||
}
|
||||
|
||||
extent_from_size :: proc ( size : AreaSize ) -> Extents2 {
|
||||
return transmute(Extents2) size * 2.0
|
||||
bounds2_radius :: proc(bounds: Bounds2) -> f32 {
|
||||
return max(bounds.bottom_right.x, bounds.top_left.y)
|
||||
}
|
||||
|
||||
extent_from_size :: proc(size: AreaSize) -> Extents2 {
|
||||
return transmute(Extents2)size * 2.0
|
||||
}
|
||||
|
||||
screen_size :: proc "contextless" () -> AreaSize {
|
||||
extent := get_state().app_window.extent
|
||||
return transmute(AreaSize) (extent * 2.0)
|
||||
return transmute(AreaSize)(extent * 2.0)
|
||||
}
|
||||
|
||||
screen_get_corners :: proc() -> BoundsCorners2 {
|
||||
state := get_state(); using state
|
||||
state := get_state();using state
|
||||
screen_extent := state.app_window.extent
|
||||
top_left := Vec2 { -screen_extent.x, screen_extent.y }
|
||||
top_right := Vec2 { screen_extent.x, screen_extent.y }
|
||||
bottom_left := Vec2 { -screen_extent.x, -screen_extent.y }
|
||||
bottom_right := Vec2 { screen_extent.x, -screen_extent.y }
|
||||
return { top_left, top_right, bottom_left, bottom_right }
|
||||
top_left := Vec2{-screen_extent.x, screen_extent.y}
|
||||
top_right := Vec2{screen_extent.x, screen_extent.y}
|
||||
bottom_left := Vec2{-screen_extent.x, -screen_extent.y}
|
||||
bottom_right := Vec2{screen_extent.x, -screen_extent.y}
|
||||
return {top_left, top_right, bottom_left, bottom_right}
|
||||
}
|
||||
|
||||
view_get_bounds :: proc() -> Bounds2 {
|
||||
state := get_state(); using state
|
||||
cam := & project.workspace.cam
|
||||
state := get_state();using state
|
||||
cam := &project.workspace.cam
|
||||
screen_extent := state.app_window.extent
|
||||
top_left := cam.target + Vec2 { -screen_extent.x, screen_extent.y }
|
||||
bottom_right := cam.target + Vec2 { screen_extent.x, -screen_extent.y }
|
||||
return { top_left, bottom_right }
|
||||
top_left := cam.target + Vec2{-screen_extent.x, screen_extent.y}
|
||||
bottom_right := cam.target + Vec2{screen_extent.x, -screen_extent.y}
|
||||
return {top_left, bottom_right}
|
||||
}
|
||||
|
||||
view_get_corners :: proc() -> BoundsCorners2 {
|
||||
state := get_state(); using state
|
||||
cam := & project.workspace.cam
|
||||
state := get_state();using state
|
||||
cam := &project.workspace.cam
|
||||
cam_zoom_ratio := 1.0 / cam.zoom
|
||||
screen_extent := state.app_window.extent * cam_zoom_ratio
|
||||
top_left := cam.target + Vec2 { -screen_extent.x, screen_extent.y }
|
||||
top_right := cam.target + Vec2 { screen_extent.x, screen_extent.y }
|
||||
bottom_left := cam.target + Vec2 { -screen_extent.x, -screen_extent.y }
|
||||
bottom_right := cam.target + Vec2 { screen_extent.x, -screen_extent.y }
|
||||
return { top_left, top_right, bottom_left, bottom_right }
|
||||
screen_extent := state.app_window.extent * cam_zoom_ratio
|
||||
top_left := cam.target + Vec2{-screen_extent.x, screen_extent.y}
|
||||
top_right := cam.target + Vec2{screen_extent.x, screen_extent.y}
|
||||
bottom_left := cam.target + Vec2{-screen_extent.x, -screen_extent.y}
|
||||
bottom_right := cam.target + Vec2{screen_extent.x, -screen_extent.y}
|
||||
return {top_left, top_right, bottom_left, bottom_right}
|
||||
}
|
||||
|
||||
screen_to_world :: proc( pos : Vec2 ) -> Vec2 {
|
||||
state := get_state(); using state
|
||||
cam := & project.workspace.cam
|
||||
return cam.target + pos * (1 / cam.zoom)
|
||||
screen_to_world :: proc(pos: Vec2) -> Vec2 {
|
||||
state := get_state();using state
|
||||
cam := &project.workspace.cam
|
||||
return vec2_pixels_to_cm(cam.target + pos * (1 / cam.zoom))
|
||||
}
|
||||
|
||||
screen_to_render :: proc( pos : Vec2 ) -> Vec2 {
|
||||
screen_extent := transmute(Vec2) get_state().project.workspace.cam.offset
|
||||
return pos + { screen_extent.x, -screen_extent.y }
|
||||
screen_to_render :: proc(pos: Vec2) -> Vec2 {
|
||||
screen_extent := transmute(Vec2)get_state().project.workspace.cam.offset
|
||||
return pos + {screen_extent.x, -screen_extent.y}
|
||||
}
|
||||
|
||||
world_screen_extent :: proc () -> Extents2 {
|
||||
state := get_state(); using state
|
||||
world_screen_extent :: proc() -> Extents2 {
|
||||
state := get_state();using state
|
||||
cam_zoom_ratio := 1.0 / project.workspace.cam.zoom
|
||||
return app_window.extent * cam_zoom_ratio
|
||||
}
|
||||
|
||||
world_to_screen_pos :: proc( position : Vec2 ) -> Vec2 {
|
||||
return { position.x, position.y * -1 }
|
||||
world_to_screen_pos :: proc(position: Vec2) -> Vec2 {
|
||||
return {position.x, position.y * -1}
|
||||
}
|
||||
|
||||
world_to_screen_no_zoom :: proc( position : Vec2 ) -> Vec2 {
|
||||
state := get_state(); using state
|
||||
world_to_screen_no_zoom :: proc(position: Vec2) -> Vec2 {
|
||||
state := get_state();using state
|
||||
cam_zoom_ratio := 1.0 / state.project.workspace.cam.zoom
|
||||
return { position.x, position.y * -1 } * cam_zoom_ratio
|
||||
return {position.x, position.y * -1} * cam_zoom_ratio
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package sectr
|
||||
import "core:unicode/utf8"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
debug_draw_text :: proc( content : string, pos : Vec2, size : f32 = 16.0, color : rl.Color = rl.WHITE, font : rl.Font = {} )
|
||||
debug_draw_text :: proc( content : string, pos : Vec2, size : f32, color : rl.Color = rl.WHITE, font : rl.Font = {} )
|
||||
{
|
||||
state := get_state(); using state
|
||||
|
||||
|
@ -19,11 +19,12 @@ render :: proc()
|
||||
rl.BeginDrawing()
|
||||
rl.ClearBackground( Color_BG )
|
||||
render_mode_2d()
|
||||
// Render Screenspace
|
||||
{
|
||||
fps_msg := fmt.tprint( "FPS:", rl.GetFPS() )
|
||||
fps_msg_width := measure_text_size( fps_msg, default_font, 16.0, 0.0 ).x
|
||||
fps_msg_width := measure_text_size( fps_msg, default_font, points_to_pixels(24.0), 0.0 ).x
|
||||
fps_msg_pos := screen_get_corners().top_right - { fps_msg_width, 0 }
|
||||
debug_draw_text( fps_msg, fps_msg_pos, color = rl.GREEN )
|
||||
debug_draw_text( fps_msg, fps_msg_pos, points_to_pixels(24.0), color = rl.GREEN )
|
||||
|
||||
debug_text :: proc( format : string, args : ..any )
|
||||
{
|
||||
@ -42,7 +43,7 @@ render :: proc()
|
||||
position.y += debug.draw_debug_text_y
|
||||
|
||||
content := fmt.bprintf( draw_text_scratch[:], format, ..args )
|
||||
debug_draw_text( content, position )
|
||||
debug_draw_text( content, position, points_to_pixels(24.0) )
|
||||
|
||||
debug.draw_debug_text_y += 16
|
||||
}
|
||||
@ -88,8 +89,8 @@ render_mode_2d :: proc() {
|
||||
}
|
||||
|
||||
for box in boxes {
|
||||
screen_pos := world_to_screen_pos(box.position) - Vec2(box.extent)
|
||||
size := transmute(Vec2) box.extent * 2.0
|
||||
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
|
||||
|
@ -158,34 +158,28 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
}
|
||||
}
|
||||
|
||||
// Frame 1 bounds detection
|
||||
{
|
||||
if debug_actions.mouse_select {
|
||||
cursor_pos := screen_to_world( input.mouse.pos )
|
||||
|
||||
box_bounds := box_get_bounds(& project.workspace.frame_1)
|
||||
within_x_bounds : b32 = cursor_pos.x >= box_bounds.top_left.x && cursor_pos.x <= box_bounds.bottom_right.x
|
||||
within_y_bounds : b32 = cursor_pos.y >= box_bounds.bottom_right.y && cursor_pos.y <= box_bounds.top_left.y
|
||||
|
||||
if within_x_bounds && within_y_bounds {
|
||||
debug.frame_1_on_top = true
|
||||
}
|
||||
}
|
||||
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 }
|
||||
}
|
||||
|
||||
// Frame 2 bounds detection
|
||||
if debug_actions.mouse_select
|
||||
{
|
||||
if debug_actions.mouse_select {
|
||||
for box in boxes
|
||||
{
|
||||
cursor_pos := screen_to_world( input.mouse.pos )
|
||||
box_extent := & project.workspace.frame_2.extent
|
||||
|
||||
box_bounds := box_get_bounds(& project.workspace.frame_2)
|
||||
|
||||
within_x_bounds : b32 = cursor_pos.x >= box_bounds.top_left.x && cursor_pos.x <= box_bounds.bottom_right.x
|
||||
within_y_bounds : b32 = cursor_pos.y >= box_bounds.bottom_right.y && cursor_pos.y <= box_bounds.top_left.y
|
||||
|
||||
if within_x_bounds && within_y_bounds {
|
||||
debug.frame_1_on_top = false
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
212
code/ui.odin
Normal file
212
code/ui.odin
Normal file
@ -0,0 +1,212 @@
|
||||
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,
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_SizeKind :: enum u32 {
|
||||
Null,
|
||||
Pixels,
|
||||
Points,
|
||||
TextContent,
|
||||
PercentOfParent,
|
||||
ChildrenSum,
|
||||
}
|
||||
|
||||
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
|
||||
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,
|
||||
}
|
||||
UI_BoxFlags :: bit_set[UI_BoxFlag; u64]
|
||||
|
||||
UI_BoxFlags_Null :: UI_BoxFlags {}
|
||||
UI_BoxFlags_Clickable :: UI_BoxFlags { .Mouse_Clickable, .Keyboard_Clickable }
|
||||
|
||||
UI_NullLabel :: ""
|
||||
|
||||
// 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,
|
||||
semantic_size : [Axis2.Count]UI_Size,
|
||||
|
||||
// Note(rjf) : Computed every frame
|
||||
computed_rel_pos : Vec2,
|
||||
computed_size : Vec2,
|
||||
//rect : Rng2F32
|
||||
|
||||
// Note(rjf) : Persistent data
|
||||
hot : f32,
|
||||
active : f32,
|
||||
|
||||
// bg_color : Color,
|
||||
// txt_color : Color,
|
||||
}
|
||||
|
||||
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_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
|
||||
}
|
@ -70,11 +70,13 @@ push-location $path_root
|
||||
|
||||
write-host "`nBuilding Sectr Prototype"
|
||||
|
||||
$module_host = join-path $path_code 'host'
|
||||
$module_sectr = $path_code
|
||||
|
||||
function build-host
|
||||
{
|
||||
$executable = join-path $path_build ($project_name + '_host.exe')
|
||||
$pdb = join-path $path_build ($project_name + '_host.pdb')
|
||||
$module_host = join-path $path_code 'host'
|
||||
|
||||
$host_process_active = Get-Process | Where-Object {$_.Name -like 'sectr_host*'}
|
||||
if ( $host_process_active ) {
|
||||
@ -82,7 +84,7 @@ push-location $path_root
|
||||
return
|
||||
}
|
||||
|
||||
$should_build = check-ModuleForChanges $module_host
|
||||
$should_build = (check-ModuleForChanges $module_host)
|
||||
if ( -not( $should_build)) {
|
||||
write-host 'Skipping sectr_host build, module up to date'
|
||||
return
|
||||
@ -106,7 +108,6 @@ push-location $path_root
|
||||
|
||||
function build-sectr
|
||||
{
|
||||
$module_sectr = $path_code
|
||||
$should_build = check-ModuleForChanges $module_sectr
|
||||
if ( -not( $should_build)) {
|
||||
write-host 'Skipping sectr build, module up to date'
|
||||
|
Loading…
Reference in New Issue
Block a user