Misc + made a more controlled digital zoom
Trying to get digital zoom to closer target levels that would match specific even font sizes Various other changes from iterating on VEFontCache
This commit is contained in:
parent
a9ddd7668f
commit
597c88c6b7
@ -55,7 +55,7 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f
|
||||
flags = {},
|
||||
anchor = range2({},{}),
|
||||
// alignment = UI_Align_Presets.text_centered,
|
||||
text_alignment = {0.0, 1.5},
|
||||
text_alignment = {0.0, 0},
|
||||
font_size = 12,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
@ -225,7 +225,7 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b
|
||||
using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins.left = 10
|
||||
layout.text_alignment = {0, 0.5}
|
||||
layout.text_alignment = {0, 0.0}
|
||||
}
|
||||
|
||||
input_box := ui_widget("settings_menu.engine_refresh.input_box", {.Mouse_Clickable, .Focusable, .Click_To_Focus}); {
|
||||
|
@ -151,10 +151,10 @@ AppConfig :: struct {
|
||||
cam_zoom_smooth_snappiness : f32,
|
||||
cam_zoom_sensitivity_smooth : f32,
|
||||
cam_zoom_sensitivity_digital : f32,
|
||||
cam_zoom_scroll_delta_scale : f32,
|
||||
|
||||
engine_refresh_hz : uint,
|
||||
|
||||
|
||||
timing_fps_moving_avg_alpha : f32,
|
||||
|
||||
ui_resize_border_width : f32,
|
||||
|
@ -69,7 +69,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
// Setup Persistent Slabs & String Cache
|
||||
{
|
||||
// alignment := uint(mem.DEFAULT_ALIGNMENT)
|
||||
alignment := uint(16)
|
||||
alignment := uint(64)
|
||||
|
||||
policy_ptr := & default_slab_policy
|
||||
push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 1 * Kilobyte, alignment })
|
||||
@ -88,9 +88,9 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 16 * Megabyte, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 32 * Megabyte, 32 * Megabyte, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 64 * Megabyte, alignment })
|
||||
// push( policy_ptr, SlabSizeClass { 128 * Megabyte, 128 * Megabyte, alignment })
|
||||
// push( policy_ptr, SlabSizeClass { 256 * Megabyte, 256 * Megabyte, alignment })
|
||||
// push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 128 * Megabyte, 128 * Megabyte, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 256 * Megabyte, 256 * Megabyte, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment })
|
||||
|
||||
alloc_error : AllocatorError
|
||||
persistent_slab, alloc_error = slab_init( policy_ptr, allocator = persistent_allocator(), dbg_name = Persistent_Slab_DBG_Name, enable_mem_tracking = false )
|
||||
@ -137,11 +137,12 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
resolution_height = 600
|
||||
refresh_rate = 0
|
||||
|
||||
cam_min_zoom = 0.10
|
||||
cam_min_zoom = 0.025
|
||||
cam_max_zoom = 5.0
|
||||
cam_zoom_mode = .Smooth
|
||||
cam_zoom_mode = .Digital
|
||||
cam_zoom_smooth_snappiness = 4.0
|
||||
cam_zoom_sensitivity_digital = 0.05
|
||||
cam_zoom_sensitivity_digital = 0.25
|
||||
cam_zoom_scroll_delta_scale = 0.25
|
||||
cam_zoom_sensitivity_smooth = 2.0
|
||||
|
||||
engine_refresh_hz = 0
|
||||
@ -252,7 +253,10 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
|
||||
// Setup sokol_gp
|
||||
{
|
||||
desc := sokol_gp.Desc {}
|
||||
desc := sokol_gp.Desc {
|
||||
max_vertices = 2 * Mega + 640 * Kilo,
|
||||
max_commands = 1 * Mega,
|
||||
}
|
||||
sokol_gp.setup(desc)
|
||||
verify( cast(b32) sokol_gp.is_valid(), "Failed to setup sokol gp (graphics painter)" )
|
||||
}
|
||||
@ -329,7 +333,9 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
}
|
||||
|
||||
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/Lorem Ipsum (197).txt", allocator = persistent_slab_allocator())
|
||||
debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/Lorem Ipsum (1022).txt", allocator = persistent_slab_allocator())
|
||||
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/Lorem Ipsum (1022).txt", allocator = persistent_slab_allocator())
|
||||
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/sokol_gp.h", allocator = persistent_slab_allocator())
|
||||
debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/ve_fontcache.h", allocator = persistent_slab_allocator())
|
||||
|
||||
alloc_error : AllocatorError; success : bool
|
||||
debug.lorem_content, success = os.read_entire_file( debug.path_lorem, persistent_slab_allocator() )
|
||||
@ -502,8 +508,8 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32
|
||||
// rl.PollInputEvents()
|
||||
|
||||
debug.draw_ui_box_bounds_points = false
|
||||
debug.draw_ui_padding_bounds = false
|
||||
debug.draw_ui_content_bounds = false
|
||||
debug.draw_ui_padding_bounds = false
|
||||
debug.draw_ui_content_bounds = false
|
||||
|
||||
// config.engine_refresh_hz = 165
|
||||
|
||||
|
@ -258,7 +258,7 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
|
||||
}
|
||||
|
||||
if true {
|
||||
state.config.font_size_canvas_scalar = 2
|
||||
state.config.font_size_canvas_scalar = 1.5
|
||||
zoom_adjust_size := 16 * state.project.workspace.cam.zoom
|
||||
over_sample := f32(state.config.font_size_canvas_scalar)
|
||||
debug_text("font_size_canvas_scalar: %v", config.font_size_canvas_scalar)
|
||||
|
@ -153,6 +153,65 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
//region 2D Camera Manual Nav
|
||||
// TODO(Ed): This should be per workspace view
|
||||
{
|
||||
Digial_Zoom_Snap_Levels := []f32{
|
||||
0.025, // 0.4px (not practical for text, but allows extreme zoom out)
|
||||
0.03125, // 0.5px
|
||||
0.0375, // 0.6px
|
||||
0.04375, // 0.7px
|
||||
0.05, // 0.8px
|
||||
0.05625, // 0.9px
|
||||
0.0625, // 1px
|
||||
0.075, // 1.2px
|
||||
0.0875, // 1.4px
|
||||
0.1, // 1.6px
|
||||
0.1125, // 1.8px
|
||||
0.125, // 2px (first practical font size)
|
||||
0.15, //
|
||||
0.20, //
|
||||
0.25, // 4px
|
||||
0.375, // 6px
|
||||
0.5, // 8px
|
||||
0.625, // 10px
|
||||
0.75, // 12px
|
||||
0.875, // 14px
|
||||
1.0, // 16px (base size)
|
||||
1.125, // 18px
|
||||
1.25, // 20px
|
||||
1.375, // 22px
|
||||
1.5, // 24px
|
||||
1.625, // 26px
|
||||
1.75, // 28px
|
||||
1.875, // 30px
|
||||
2.0, // 32px
|
||||
2.125, // 34px
|
||||
2.25, // 36px
|
||||
2.375, // 38px
|
||||
2.5, // 40px
|
||||
2.625, // 42px
|
||||
2.75, // 44px
|
||||
2.875, // 46px
|
||||
3.0, // 48px
|
||||
3.125, // 50px
|
||||
3.25, // 52px
|
||||
3.375, // 54px
|
||||
3.5, // 56px
|
||||
3.625, // 58px
|
||||
3.75, // 60px
|
||||
3.875, // 62px
|
||||
4.0, // 64px
|
||||
4.125, // 66px
|
||||
4.25, // 68px
|
||||
4.375, // 70px
|
||||
4.5, // 72px
|
||||
4.625, // 74px
|
||||
4.75, // 76px
|
||||
4.875, // 78px
|
||||
5.0, // 80px
|
||||
}
|
||||
|
||||
Min_Zoom := Digial_Zoom_Snap_Levels[ 0 ]
|
||||
Max_zoom := Digial_Zoom_Snap_Levels[ len(Digial_Zoom_Snap_Levels) - 1 ]
|
||||
|
||||
// profile("Camera Manual Nav")
|
||||
digital_move_speed : f32 = 1000.0
|
||||
|
||||
@ -160,11 +219,30 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
workspace.zoom_target = cam.zoom
|
||||
}
|
||||
|
||||
// config.cam_max_zoom = 10
|
||||
// config.cam_min_zoom = 0.05
|
||||
// config.cam_zoom_sensitivity_digital = 0.05
|
||||
// config.cam_zoom_sensitivity_smooth = 2.0
|
||||
// config.cam_zoom_mode = .Smooth
|
||||
binary_search_closest :: proc(arr: []f32, target: f32) -> int
|
||||
{
|
||||
low, high := 0, len(arr) - 1
|
||||
|
||||
for low <= high {
|
||||
mid := (low + high) / 2
|
||||
if arr[ mid ] == target do return mid
|
||||
else if arr[ mid ] < target do low = mid + 1
|
||||
else do high = mid - 1
|
||||
}
|
||||
|
||||
if low == 0 do return 0
|
||||
if low == len(arr) do return len(arr) - 1
|
||||
|
||||
if abs(arr[low-1] - target) < abs(arr[low] - target) {
|
||||
return low - 1
|
||||
}
|
||||
return low
|
||||
}
|
||||
|
||||
find_closest_zoom_index :: proc(zoom: f32, levels : []f32) -> int {
|
||||
return clamp(binary_search_closest(levels, zoom), 0, len(levels) - 1)
|
||||
}
|
||||
|
||||
switch config.cam_zoom_mode
|
||||
{
|
||||
case .Smooth:
|
||||
@ -177,9 +255,26 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
cam.zoom += (workspace.zoom_target - cam.zoom) * lerp_factor * f32(delta_time)
|
||||
cam.zoom = clamp(cam.zoom, config.cam_min_zoom, config.cam_max_zoom) // Ensure cam.zoom stays within bounds
|
||||
case .Digital:
|
||||
zoom_delta := clamp(input.mouse.scroll.y, -1, 1) * config.cam_zoom_sensitivity_digital
|
||||
workspace.zoom_target = clamp(workspace.zoom_target + zoom_delta, config.cam_min_zoom, config.cam_max_zoom)
|
||||
cam.zoom = workspace.zoom_target
|
||||
zoom_delta := input.mouse.scroll.y
|
||||
|
||||
if zoom_delta != 0 {
|
||||
current_index := find_closest_zoom_index(cam.zoom, Digial_Zoom_Snap_Levels)
|
||||
scroll_speed := max(1, abs(zoom_delta) * config.cam_zoom_scroll_delta_scale) // Adjust this factor to control sensitivity
|
||||
target_index := current_index
|
||||
|
||||
if zoom_delta > 0 {
|
||||
target_index = min(len(Digial_Zoom_Snap_Levels) - 1, current_index + int(scroll_speed))
|
||||
} else if zoom_delta < 0 {
|
||||
target_index = max(0, current_index - int(scroll_speed))
|
||||
}
|
||||
|
||||
if target_index != current_index {
|
||||
workspace.zoom_target = Digial_Zoom_Snap_Levels[target_index]
|
||||
}
|
||||
}
|
||||
|
||||
// Smooth transition to target zoom
|
||||
cam.zoom = lerp(cam.zoom, workspace.zoom_target, cast(f32) config.cam_zoom_sensitivity_digital)
|
||||
}
|
||||
|
||||
move_velocity : Vec2 = {
|
||||
|
@ -51,6 +51,7 @@ import fmt_io "core:fmt"
|
||||
str_tmp_from_any :: fmt_io.tprint
|
||||
|
||||
import "core:math"
|
||||
lerp :: math.lerp
|
||||
|
||||
import "core:math/bits"
|
||||
u64_max :: bits.U64_MAX
|
||||
|
@ -205,7 +205,8 @@ render_to_ws_view_pos :: #force_inline proc "contextless" (pos : Vec2) -> Vec2 {
|
||||
screen_to_ws_view_pos :: #force_inline proc "contextless" (pos: Vec2) -> Vec2 {
|
||||
state := get_state(); using state
|
||||
cam := & project.workspace.cam
|
||||
result := pos - cam.position * cam.zoom
|
||||
cam_zoom_ratio := 1.0 / cam.zoom
|
||||
result := pos * cam_zoom_ratio - cam.position
|
||||
return result
|
||||
}
|
||||
|
||||
@ -227,8 +228,17 @@ ws_view_extent :: #force_inline proc "contextless"() -> Extents2 {
|
||||
|
||||
// Workspace view to screen space position
|
||||
// TODO(Ed): Support a position which would not be centered on the screen if in a viewport
|
||||
ws_view_to_screen_pos :: #force_inline proc "contextless"(position: Vec2) -> Vec2 {
|
||||
return position
|
||||
ws_view_to_screen_pos :: proc(ws_pos : Vec2) -> Vec2 {
|
||||
cam := &get_state().project.workspace.cam
|
||||
screen_extent := get_state().app_window.extent
|
||||
|
||||
// Apply camera transformation
|
||||
view_pos := (ws_pos - cam.position) * cam.zoom
|
||||
|
||||
// Convert to screen space
|
||||
screen_pos := view_pos
|
||||
|
||||
return screen_pos
|
||||
}
|
||||
|
||||
ws_view_to_render_pos :: #force_inline proc "contextless"(position: Vec2) -> Vec2 {
|
||||
|
@ -504,15 +504,16 @@ 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 {
|
||||
|
||||
ui_view_bounds :: #force_inline proc "contextless" ( ui : ^UI_State = nil ) -> (range : Range2) {
|
||||
state := get_state(); using state
|
||||
ui := ui; if ui == nil do ui = ui_context
|
||||
|
||||
if ui == & screen_ui {
|
||||
return screen_get_bounds()
|
||||
}
|
||||
else {
|
||||
return view_get_bounds()
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
ui_context :: #force_inline proc "contextless" () -> ^UI_State { return get_state().ui_context }
|
||||
|
@ -118,36 +118,33 @@ ui_prev_cached_box :: #force_inline proc( box : ^UI_Box ) -> ^UI_Box { return hm
|
||||
|
||||
// TODO(Ed): Rename to ui_box_tranverse_view_next
|
||||
// Traveral pritorizes immeidate children
|
||||
ui_box_tranverse_next_depth_first :: #force_inline proc "contextless" ( box : ^ UI_Box, bypass_intersection_test := false ) -> (^ UI_Box)
|
||||
{
|
||||
using state := get_state()
|
||||
// If current has children, do them first
|
||||
if box.first != nil
|
||||
{
|
||||
// Check to make sure parent is present on the screen, if its not don't bother.
|
||||
if bypass_intersection_test {
|
||||
return box.first
|
||||
}
|
||||
if intersects_range2( ui_view_bounds(), box.computed.bounds) {
|
||||
return box.first
|
||||
ui_box_tranverse_next_depth_first :: #force_inline proc "contextless" (box: ^UI_Box, bypass_intersection_test := false, ctx: ^UI_State = nil) -> ^UI_Box {
|
||||
state := get_state(); using state
|
||||
ctx := ctx if ctx != nil else ui_context
|
||||
|
||||
// If current has children, check if we should traverse them
|
||||
if box.first != nil {
|
||||
if bypass_intersection_test || intersects_range2(ui_view_bounds(ctx), box.computed.bounds) {
|
||||
return box.first
|
||||
}
|
||||
}
|
||||
|
||||
if box.next != nil do return box.next
|
||||
// There are no more adjacent nodes
|
||||
// If no children or children are culled, try next sibling
|
||||
if box.next != nil {
|
||||
return box.next
|
||||
}
|
||||
|
||||
// No more siblings, traverse up the tree
|
||||
parent := box.parent
|
||||
// Attempt to find a parent with a next, otherwise we just return a parent with nil
|
||||
for ; parent.parent != nil;
|
||||
{
|
||||
if parent.next != nil {
|
||||
break
|
||||
}
|
||||
parent = parent.parent
|
||||
for parent != nil {
|
||||
if parent.next != nil {
|
||||
return parent.next
|
||||
}
|
||||
parent = parent.parent
|
||||
}
|
||||
|
||||
// Lift back up to parent, and set it to its next.
|
||||
return parent.next
|
||||
// We've reached the end of the tree
|
||||
return nil
|
||||
}
|
||||
|
||||
// Traveral pritorizes traversing a "anestry layer"
|
||||
|
@ -166,9 +166,11 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
|
||||
// 8. Text position & size
|
||||
if len(box.text.str) > 0
|
||||
{
|
||||
ascent, descent, line_gap := get_font_vertical_metrics(style.font, layout.font_size)
|
||||
content_size := content_bounds.max - content_bounds.min
|
||||
text_pos : Vec2
|
||||
text_pos = content_bounds.min + { 0, text_size.y * 0.5 }
|
||||
text_pos = content_bounds.min
|
||||
text_pos += { 0, -descent }
|
||||
text_pos += (content_size - text_size) * layout.text_alignment
|
||||
|
||||
computed.text_size = text_size
|
||||
|
@ -163,17 +163,17 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
text_layout.flags = {
|
||||
// .Origin_At_Anchor_Center,
|
||||
.Fixed_Position_X, .Fixed_Position_Y,
|
||||
.Fixed_Width, .Fixed_Height,
|
||||
.Fixed_Width, .Fixed_Height,
|
||||
}
|
||||
text_layout.text_alignment = { 0.0, 0.5 }
|
||||
text_layout.alignment = { 0.0, 0.0 }
|
||||
text_layout.size.min = { 1600, 20 }
|
||||
text_layout.alignment = { 0.0, 1.0 }
|
||||
text_layout.size.min = { 1600, 14 }
|
||||
text_style := frame_style_default ^
|
||||
text_style_combo := to_ui_style_combo(text_style)
|
||||
text_style_combo.default.bg_color = Color_Transparent
|
||||
text_style_combo.disabled.bg_color = Color_Frame_Disabled
|
||||
text_style_combo.hot.bg_color = Color_Frame_Hover
|
||||
text_style_combo.active.bg_color = Color_Frame_Select
|
||||
text_style_combo.disabled.bg_color = Color_Transparent
|
||||
text_style_combo.hot.bg_color = Color_Transparent
|
||||
text_style_combo.active.bg_color = Color_Transparent
|
||||
scope( text_layout, text_style )
|
||||
|
||||
alloc_error : AllocatorError; success : bool
|
||||
@ -204,14 +204,14 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
ui_layout( text_layout )
|
||||
line_hbox := ui_widget(str_fmt( "line %v", line_id ), {.Mouse_Clickable})
|
||||
|
||||
if line_hbox.key == ui.hot
|
||||
if line_hbox.key == ui.hot && false
|
||||
{
|
||||
line_hbox.text = StrRunesPair {}
|
||||
ui_parent(line_hbox)
|
||||
|
||||
chunk_layout := text_layout
|
||||
chunk_layout.alignment = { 0.0, 0.5 }
|
||||
chunk_layout.anchor = range2({ 0.0, 0 }, { 0.0, 0 })
|
||||
chunk_layout.alignment = { 0.0, 0.0 }
|
||||
chunk_layout.anchor = range2({ 0.0, 0.0 }, { 0.0, 0.0 })
|
||||
chunk_layout.pos = {}
|
||||
chunk_layout.flags = { .Fixed_Position_X, .Size_To_Text }
|
||||
|
||||
@ -286,12 +286,12 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
if len(line_hbox.text.str) > 0 {
|
||||
array_append( widgets_ptr, line_hbox )
|
||||
text_layout.pos.x = text_layout.pos.x
|
||||
text_layout.pos.y += size_range2(line_hbox.computed.bounds).y - 8
|
||||
text_layout.pos.y += size_range2(line_hbox.computed.bounds).y
|
||||
}
|
||||
else {
|
||||
widget := & widgets.data[ widgets.num - 1 ]
|
||||
if widget.box != nil {
|
||||
text_layout.pos.y += size_range2( widget.computed.bounds ).y - 8
|
||||
text_layout.pos.y += size_range2( widget.computed.bounds ).y
|
||||
}
|
||||
}
|
||||
|
||||
|
2978
examples/sokol_gp.h
Normal file
2978
examples/sokol_gp.h
Normal file
File diff suppressed because it is too large
Load Diff
1799
examples/ve_fontcache.h
Normal file
1799
examples/ve_fontcache.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -204,10 +204,10 @@ 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_none
|
||||
# $build_args += $flag_optimize_minimal
|
||||
# $build_args += $flag_optimize_speed
|
||||
# $build_args += $falg_optimize_aggressive
|
||||
$build_args += $falg_optimize_aggressive
|
||||
$build_args += $flag_debug
|
||||
$build_args += $flag_pdb_name + $pdb
|
||||
$build_args += $flag_subsystem + 'windows'
|
||||
|
Loading…
Reference in New Issue
Block a user