diff --git a/.gitignore b/.gitignore index a69ff92..2df1b27 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ ols.json .vscode/settings.json *.spall sectr.user +sectr.proj diff --git a/code/grime/array.odin b/code/grime/array.odin index 8c5518f..d8518d2 100644 --- a/code/grime/array.odin +++ b/code/grime/array.odin @@ -37,8 +37,8 @@ array_underlying_slice :: proc(slice: []($ Type)) -> Array(Type) return array } -array_to_slice :: #force_inline proc( using self : Array($ Type) ) -> []Type { return slice_ptr( data, int(num)) } -array_to_slice_capacity :: #force_inline proc( using self : Array($ Type) ) -> []Type { return slice_ptr( data, int(capacity)) } +array_to_slice :: #force_inline proc "contextless" ( using self : Array($ Type) ) -> []Type { return slice_ptr( data, int(num)) } +array_to_slice_capacity :: #force_inline proc "contextless" ( using self : Array($ Type) ) -> []Type { return slice_ptr( data, int(capacity)) } array_grow_formula :: proc( value : u64 ) -> u64 { result := (2 * value) + 8 diff --git a/code/grime/hashmap_kt1cx.odin b/code/grime/hashmap_kt1cx.odin index 2540a82..3eaf9d8 100644 --- a/code/grime/hashmap_kt1cx.odin +++ b/code/grime/hashmap_kt1cx.odin @@ -1,48 +1,2 @@ package grime -when (false) { - -KT1L_Slot :: struct($Type: typeid) { - key: u64, - value: Type, -} -KT1L_Meta :: struct { - slot_size: uintptr, - kt_value_offset: uintptr, - type_width: uintptr, - type_name: string, -} -kt1l_populate_slice_a2_Slice_Byte :: proc(kt: ^[]byte, backing: Allocator = context.allocator, values: []byte, num_values: int, m: KT1L_Meta) { - assert(kt != nil) - if num_values == 0 { return } - table_size_bytes := num_values * int(m.slot_size) - err : AllocatorError - kt^, err = alloc_bytes(table_size_bytes, allocator = backing) - slice_assert(kt ^) - kt_raw : Raw_Slice = transmute(Raw_Slice) kt^ - for cursor in 0 ..< cast(uintptr) num_values { - slot_offset := cursor * m.slot_size - slot_cursor := uintptr(kt_raw.data) + slot_offset - slot_key := cast(^u64) slot_cursor - slot_value := transmute([]byte) Raw_Slice { cast([^]byte) (slot_cursor + m.kt_value_offset), int(m.type_width)} - a2_offset := cursor * m.type_width * 2 - a2_cursor := uintptr(& values[a2_offset]) - a2_key := (transmute(^[]byte) a2_cursor) ^ - a2_value := transmute([]byte) Raw_Slice { rawptr(a2_cursor + m.type_width), int(m.type_width) } - copy(slot_value, a2_value) - slot_key^ = 0; hash64_djb8(slot_key, a2_key) - } - kt_raw.len = num_values -} -kt1l_populate_slice_a2 :: proc($Type: typeid, kt: ^[]KT1L_Slot(Type), backing: AllocatorInfo, values: [][2]Type) { - assert(kt != nil) - values_bytes := transmute([]byte) Raw_Slice{data = raw_data(values), len = len(values) * size_of([2]Type)} - kt1l_populate_slice_a2_Slice_Byte(transmute(^[]byte) kt, backing, values_bytes, len(values), { - slot_size = size_of(KT1L_Slot(Type)), - kt_value_offset = offset_of(KT1L_Slot(Type), KT1L_Slot(Type).value), - type_width = size_of(Type), - type_name = #type_string(Type), - }) -} - -} \ No newline at end of file diff --git a/code/grime/hashmap_kt1l.odin b/code/grime/hashmap_kt1l.odin index 9f9e224..83926e2 100644 --- a/code/grime/hashmap_kt1l.odin +++ b/code/grime/hashmap_kt1l.odin @@ -1 +1,48 @@ package grime + +when (false) { + +KT1L_Slot :: struct($Type: typeid) { + key: u64, + value: Type, +} +KT1L_Meta :: struct { + slot_size: uintptr, + kt_value_offset: uintptr, + type_width: uintptr, + type_name: string, +} +kt1l_populate_slice_a2_Slice_Byte :: proc(kt: ^[]byte, backing: Allocator = context.allocator, values: []byte, num_values: int, m: KT1L_Meta) { + assert(kt != nil) + if num_values == 0 { return } + table_size_bytes := num_values * int(m.slot_size) + err : AllocatorError + kt^, err = alloc_bytes(table_size_bytes, allocator = backing) + slice_assert(kt ^) + kt_raw : Raw_Slice = transmute(Raw_Slice) kt^ + for cursor in 0 ..< cast(uintptr) num_values { + slot_offset := cursor * m.slot_size + slot_cursor := uintptr(kt_raw.data) + slot_offset + slot_key := cast(^u64) slot_cursor + slot_value := transmute([]byte) Raw_Slice { cast([^]byte) (slot_cursor + m.kt_value_offset), int(m.type_width)} + a2_offset := cursor * m.type_width * 2 + a2_cursor := uintptr(& values[a2_offset]) + a2_key := (transmute(^[]byte) a2_cursor) ^ + a2_value := transmute([]byte) Raw_Slice { rawptr(a2_cursor + m.type_width), int(m.type_width) } + copy(slot_value, a2_value) + slot_key^ = 0; hash64_djb8(slot_key, a2_key) + } + kt_raw.len = num_values +} +kt1l_populate_slice_a2 :: proc($Type: typeid, kt: ^[]KT1L_Slot(Type), backing: AllocatorInfo, values: [][2]Type) { + assert(kt != nil) + values_bytes := transmute([]byte) Raw_Slice{data = raw_data(values), len = len(values) * size_of([2]Type)} + kt1l_populate_slice_a2_Slice_Byte(transmute(^[]byte) kt, backing, values_bytes, len(values), { + slot_size = size_of(KT1L_Slot(Type)), + kt_value_offset = offset_of(KT1L_Slot(Type), KT1L_Slot(Type).value), + type_width = size_of(Type), + type_name = #type_string(Type), + }) +} + +} diff --git a/code/grime/string_cache.odin b/code/grime/string_cache.odin index 18d6e87..45effb8 100644 --- a/code/grime/string_cache.odin +++ b/code/grime/string_cache.odin @@ -64,7 +64,7 @@ str_cache_init :: proc( table_allocator, slabs_allocator : Allocator ) -> (cache @static dbg_name := "StringCache slab" - // TODO(Ed): Is this nessary (essentially is there a perf impact of using vs not using, which is better because thats all that matters) + // TODO(Ed): Is this necessary (essentially is there a perf impact of using vs not using, which is better because thats all that matters) // Interning should only be handled on a growing arena anyway so it doesn't really need this. alloc_error : AllocatorError cache.slab, alloc_error = slab_init( & policy, allocator = slabs_allocator, dbg_name = dbg_name ) diff --git a/code/sectr/app/state.odin b/code/sectr/app/state.odin index 1f97659..9d0f201 100644 --- a/code/sectr/app/state.odin +++ b/code/sectr/app/state.odin @@ -216,9 +216,10 @@ State :: struct { input_data : [2]InputState, input_prev : ^InputState, - input : ^InputState, + input : ^InputState, // TODO(Ed): Rename to indicate its the device's signal state for the frame? - input_events : InputEvents, + input_events: InputEvents, + input_binds_stack: Array(InputContext), // Note(Ed): Do not modify directly, use its interface in app/event.odin staged_input_events : Array(InputEvent), @@ -292,4 +293,7 @@ get_screen_extent :: #force_inline proc "contextless" () -> Extents2 { retu get_ui_context_mut :: #force_inline proc "contextless" () -> ^UI_State { return get_state().ui_context } set_ui_context :: #force_inline proc "contextless" ( ui : ^UI_State ) { get_state().ui_context = ui } +get_input_binds :: #force_inline proc "contextless" () -> InputContext { return array_back(get_state().input_binds_stack) } +get_input_binds_stack :: #force_inline proc "contextless" () -> []InputContext { return array_to_slice(get_state().input_binds_stack) } + //endregion State diff --git a/code/sectr/engine/client_api.odin b/code/sectr/engine/client_api.odin index 7b867db..e184de7 100644 --- a/code/sectr/engine/client_api.odin +++ b/code/sectr/engine/client_api.odin @@ -536,7 +536,7 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32 debug.draw_ui_box_bounds_points = false debug.draw_ui_padding_bounds = false - debug.draw_ui_content_bounds = false + debug.draw_ui_content_bounds = true // config.engine_refresh_hz = 165 diff --git a/code/sectr/engine/render.odin b/code/sectr/engine/render.odin index 291795a..7638356 100644 --- a/code/sectr/engine/render.odin +++ b/code/sectr/engine/render.odin @@ -454,6 +454,13 @@ render_ui_via_box_list :: proc( box_list : []UI_RenderBoxInfo, text_list : []UI_ shape_enqueued = true } + if debug.draw_ui_content_bounds + { + render_set_color(RGBA8_Debug_UI_Content_Bounds) + draw_rect_border(entry.bounds, 1.0) + shape_enqueued = true + } + box_id += 1 } @@ -890,4 +897,4 @@ render_set_view_space :: #force_inline proc( extent : Extents2 ) gp.project( -extent.x, extent.x, extent.y, -extent.y ) } -//endregion Helpers +//endregion Helper \ No newline at end of file diff --git a/code/sectr/grime/pkg_mappings.odin b/code/sectr/grime/pkg_mappings.odin index 039b368..f891eba 100644 --- a/code/sectr/grime/pkg_mappings.odin +++ b/code/sectr/grime/pkg_mappings.odin @@ -124,6 +124,8 @@ import "core:os" import "core:path/filepath" file_name_from_path :: filepath.short_stem +import "core:slice" + import "core:strconv" parse_f32 :: strconv.parse_f32 parse_u64 :: strconv.parse_u64 @@ -194,6 +196,7 @@ import "codebase:grime" array_append_value :: grime.array_append_value array_append_array :: grime.array_append_array array_append_at :: grime.array_append_at + array_back :: grime.array_back array_clear :: grime.array_clear array_free :: grime.array_free array_grow_formula :: grime.array_grow_formula @@ -366,6 +369,10 @@ append_at :: proc { grime.array_append_at_slice, } +back :: proc { + grime.array_back, +} + bivec3 :: proc { bivec3_via_f32s, vec3_to_bivec3, @@ -426,7 +433,7 @@ floor :: proc { math.floor_f64le, math.floor_f64be, - linalg.floor + linalg.floor, } from_bytes :: proc { @@ -717,4 +724,8 @@ wedge :: proc { wedge_bivec3, } +zero :: proc { + slice.zero, +} + //endregion Proc overload mappings diff --git a/code/sectr/ui/core/base.odin b/code/sectr/ui/core/base.odin index 28692ae..128a251 100644 --- a/code/sectr/ui/core/base.odin +++ b/code/sectr/ui/core/base.odin @@ -48,6 +48,7 @@ UI_InteractState :: struct { disabled_time : f32, } +// TODO(Ed): Make the key 128-bit? UI_Key :: distinct u64 UI_Scalar :: f32 diff --git a/code/sectr/ui/core/layout_compute.odin b/code/sectr/ui/core/layout_compute.odin index c754400..cd94856 100644 --- a/code/sectr/ui/core/layout_compute.odin +++ b/code/sectr/ui/core/layout_compute.odin @@ -1,5 +1,163 @@ package sectr +ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_LayoutDirection_X, width_ref : ^f32 = nil ) +{ + container_width : f32 + if width_ref != nil { + container_width = width_ref ^ + } + 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 + size_req_children : f32 = 0 + for child := container.first; child != nil; child = child.next + { + 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 + { + size_req_children += size.min.x + continue + } + + size_req_children += size.min.x + total_stretch_ratio += anchor.ratio.x + } + + avail_flex_space := container_width - size_req_children + + allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space, container_height : f32 ) -> (space_allocated : f32) + { + using child.layout + 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) { + potential_size := anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space + space_allocated = max(potential_size, size.min.x) + size.min.x = space_allocated + } + else { + space_allocated = size.min.x + } + space_allocated -= margins.left - margins.right + size.min.x -= margins.left - margins.right + flags |= {.Fixed_Width} + return + } + + space_used : f32 = 0.0 + switch direction{ + case .Left_To_Right: + for child := container.first; child != nil; child = child.next { + using child.layout + child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height) + anchor = range2({0, anchor.bottom}, {0, anchor.top}) + alignment = {0, alignment.y} + pos.x = space_used + space_used += child_width + child.layout.margins.left + child.layout.margins.right + } + case .Right_To_Left: + for child := container.first; child != nil; child = child.next { + using child.layout + child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height) + anchor = range2({1, anchor.bottom}, {0, anchor.top}) + alignment = {1, alignment.y} + pos.x = space_used + space_used -= child_width + child.layout.margins.left + child.layout.margins.right + } + } +} + +ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_LayoutDirection_Y, height_ref : ^f32 = nil ) +{ + container_height : f32 + if height_ref != nil { + container_height = height_ref ^ + } + else { + container_height = container.computed.content.max.y - container.computed.content.min.y + } + container_width := container.computed.content.max.x - container.computed.content.min.x + + // do layout calculations for the children + total_stretch_ratio : f32 = 0.0 + size_req_children : f32 = 0 + for child := container.first; child != nil; child = child.next + { + using child.layout + scaled_height_by_width : b32 = b32(.Scale_Height_By_Width_Ratio in flags) + if scaled_height_by_width { + size_req_children += size.min.y * container_width + continue + } + if .Fixed_Height in flags + { + size_req_children += size.min.y + continue + } + + size_req_children += size.min.y + total_stretch_ratio += anchor.ratio.y + } + + avail_flex_space := container_height - size_req_children + + allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space, container_width : f32 ) -> (space_allocated : f32) + { + using child.layout + if .Scale_Height_By_Width_Ratio in flags { + size.min.x = container_width + space_allocated = size.min.y * container_width + } + if ! (.Fixed_Height in flags) { + potential_size := (anchor.ratio.y * (1 / total_stretch_ratio) * avail_flex_space) + space_allocated = max(potential_size, size.min.y) + size.min.y = space_allocated + } + else { + space_allocated = size.min.y + } + space_allocated -= margins.top - margins.bottom + size.min.y -= margins.top - margins.bottom + flags |= {.Fixed_Height} + return + } + + space_used : f32 = 0 + switch direction + { + case .Top_To_Bottom: + for child := container.first; child != nil; child = child.next { + using child.layout + child_height := allocate_space(child, total_stretch_ratio, avail_flex_space, container_width) + anchor = range2({anchor.left, 1}, {anchor.right, 0}) + alignment = {alignment.x, 1} + pos.y = space_used + space_used -= child_height - child.layout.margins.top - child.layout.margins.bottom + } + case .Bottom_To_Top: + for child := container.first; child != nil; child = child.next { + using child.layout + child_height := allocate_space(child, total_stretch_ratio, avail_flex_space, container_width) + anchor = range2({anchor.left,0}, {anchor.right, 0}) + alignment = {alignment.x, 0} + pos.y = space_used + space_used += child_height - child.layout.margins.top - child.layout.margins.bottom + } + } +} + ui_box_compute_layout :: proc( box : ^UI_Box, dont_mark_fresh : b32 = false, ancestors_layout_required : b32 = false, diff --git a/code/sectr/ui/layout_widget.odin b/code/sectr/ui/layout_widget.odin index 9fbf9ba..8054e62 100644 --- a/code/sectr/ui/layout_widget.odin +++ b/code/sectr/ui/layout_widget.odin @@ -8,161 +8,3 @@ Widget Layout Ops TODO(Ed): Review this file, these are can now be done with ui_box_compute_layout */ - -ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_LayoutDirection_X, width_ref : ^f32 = nil ) -{ - container_width : f32 - if width_ref != nil { - container_width = width_ref ^ - } - 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 - size_req_children : f32 = 0 - for child := container.first; child != nil; child = child.next - { - 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 - { - size_req_children += size.min.x - continue - } - - size_req_children += size.min.x - total_stretch_ratio += anchor.ratio.x - } - - avail_flex_space := container_width - size_req_children - - allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space, container_height : f32 ) -> (space_allocated : f32) - { - using child.layout - 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) { - potential_size := anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space - space_allocated = lalg.max(potential_size, size.min.x) - size.min.x = space_allocated - } - else { - space_allocated = size.min.x - } - space_allocated -= margins.left - margins.right - size.min.x -= margins.left - margins.right - flags |= {.Fixed_Width} - return - } - - space_used : f32 = 0.0 - switch direction{ - case .Left_To_Right: - for child := container.first; child != nil; child = child.next { - using child.layout - child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height) - anchor = range2({0, anchor.bottom}, {0, anchor.top}) - alignment = {0, alignment.y} - pos.x = space_used - space_used += child_width + child.layout.margins.left + child.layout.margins.right - } - case .Right_To_Left: - for child := container.first; child != nil; child = child.next { - using child.layout - child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height) - anchor = range2({1, anchor.bottom}, {0, anchor.top}) - alignment = {1, alignment.y} - pos.x = space_used - space_used -= child_width + child.layout.margins.left + child.layout.margins.right - } - } -} - -ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_LayoutDirection_Y, height_ref : ^f32 = nil ) -{ - container_height : f32 - if height_ref != nil { - container_height = height_ref ^ - } - else { - container_height = container.computed.content.max.y - container.computed.content.min.y - } - container_width := container.computed.content.max.x - container.computed.content.min.x - - // do layout calculations for the children - total_stretch_ratio : f32 = 0.0 - size_req_children : f32 = 0 - for child := container.first; child != nil; child = child.next - { - using child.layout - scaled_height_by_width : b32 = b32(.Scale_Height_By_Width_Ratio in flags) - if scaled_height_by_width { - size_req_children += size.min.y * container_width - continue - } - if .Fixed_Height in flags - { - size_req_children += size.min.y - continue - } - - size_req_children += size.min.y - total_stretch_ratio += anchor.ratio.y - } - - avail_flex_space := container_height - size_req_children - - allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space, container_width : f32 ) -> (space_allocated : f32) - { - using child.layout - if .Scale_Height_By_Width_Ratio in flags { - size.min.x = container_width - space_allocated = size.min.y * container_width - } - if ! (.Fixed_Height in flags) { - potential_size := (anchor.ratio.y * (1 / total_stretch_ratio) * avail_flex_space) - space_allocated = lalg.max(potential_size, size.min.y) - size.min.y = space_allocated - } - else { - space_allocated = size.min.y - } - space_allocated -= margins.top - margins.bottom - size.min.y -= margins.top - margins.bottom - flags |= {.Fixed_Height} - return - } - - space_used : f32 = 0 - switch direction - { - case .Top_To_Bottom: - for child := container.first; child != nil; child = child.next { - using child.layout - child_height := allocate_space(child, total_stretch_ratio, avail_flex_space, container_width) - anchor = range2({anchor.left, 1}, {anchor.right, 0}) - alignment = {alignment.x, 1} - pos.y = space_used - space_used -= child_height - child.layout.margins.top - child.layout.margins.bottom - } - case .Bottom_To_Top: - for child := container.first; child != nil; child = child.next { - using child.layout - child_height := allocate_space(child, total_stretch_ratio, avail_flex_space, container_width) - anchor = range2({anchor.left,0}, {anchor.right, 0}) - alignment = {alignment.x, 0} - pos.y = space_used - space_used += child_height - child.layout.margins.top - child.layout.margins.bottom - } - } -} diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 9020eba..5f0aad3 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -209,10 +209,10 @@ push-location $path_root $build_args += $flag_use_separate_modules $build_args += $flag_thread_count + $CoreCount_Physical # $build_args += $flag_optimize_none - # $build_args += $flag_optimize_minimal - $build_args += $flag_optimize_speed + $build_args += $flag_optimize_minimal + # $build_args += $flag_optimize_speed # $build_args += $falg_optimize_aggressive - # $build_args += $flag_debug + $build_args += $flag_debug $build_args += $flag_pdb_name + $pdb $build_args += $flag_subsystem + 'windows' # $build_args += $flag_show_system_calls @@ -289,8 +289,8 @@ push-location $path_root # $build_args += $flag_micro_architecture_native $build_args += $flag_use_separate_modules $build_args += $flag_thread_count + $CoreCount_Physical - $build_args += $flag_optimize_none - # $build_args += $flag_optimize_minimal + # $build_args += $flag_optimize_none + $build_args += $flag_optimize_minimal # $build_args += $flag_optimize_speed # $build_args += $falg_optimize_aggressive $build_args += $flag_debug diff --git a/sectr.proj b/sectr.proj deleted file mode 100644 index a3940ec..0000000 --- a/sectr.proj +++ /dev/null @@ -1,9 +0,0 @@ -// raddbg 0.9.18 project file - -recent_file: path: "code/host/host.odin" -target: -{ - executable: "build/sectr_host.exe" - working_directory: build - enabled: 1 -}