Remove rune tracking for string cache, + vecache changes
Getting ready to de-hardcode vefontcache shaders
This commit is contained in:
parent
f1f98ffafb
commit
0350a0c282
@ -249,6 +249,23 @@ generate_glyph_pass_draw_list :: proc(draw_list : ^Draw_List, path : ^[dynamic]V
|
||||
}
|
||||
}
|
||||
|
||||
generate_shapes_draw_list :: proc ( ctx : ^Context, font : Font_ID, colour : Colour, entry : Entry, font_scale : f32, position, scale : Vec2, shapes : []Shaped_Text )
|
||||
{
|
||||
assert(len(shapes) > 0)
|
||||
for shape in shapes {
|
||||
ctx.cursor_pos = {}
|
||||
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
|
||||
colour,
|
||||
entry,
|
||||
font_scale,
|
||||
position,
|
||||
scale,
|
||||
ctx.snap_width,
|
||||
ctx.snap_height
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
generate_shape_draw_list :: #force_no_inline proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
atlas : ^Atlas,
|
||||
glyph_buffer : ^Glyph_Draw_Buffer,
|
||||
@ -626,12 +643,12 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
|
||||
dst_glyph_pos := glyph.region_pos
|
||||
dst_glyph_size := glyph.bounds_size_scaled + atlas.glyph_padding
|
||||
// dst_glyph_size.y = ceil(dst_glyph_size.y) // Note(Ed): Seems to improve hinting
|
||||
dst_glyph_size.y = ceil(dst_glyph_size.y) // Note(Ed): Seems to improve hinting
|
||||
to_glyph_buffer_space( & dst_glyph_pos, & dst_glyph_size, atlas_size )
|
||||
|
||||
src_position := Vec2 { glyph.buffer_x, 0 }
|
||||
src_size := (glyph.bounds_size_scaled + atlas.glyph_padding) * glyph_buffer.over_sample
|
||||
// src_size.y = ceil(src_size.y) // Note(Ed): Seems to improve hinting
|
||||
src_size := (glyph.bounds_size_scaled + atlas.glyph_padding) * glyph_buffer.over_sample
|
||||
src_size.y = ceil(src_size.y) // Note(Ed): Seems to improve hinting
|
||||
to_target_space( & src_position, & src_size, glyph_buffer_size )
|
||||
|
||||
blit_to_atlas : Draw_Call
|
||||
|
@ -90,6 +90,7 @@ make :: proc {
|
||||
make_dynamic_array,
|
||||
make_dynamic_array_len,
|
||||
make_dynamic_array_len_cap,
|
||||
make_slice,
|
||||
make_map,
|
||||
make_map_cap,
|
||||
}
|
||||
|
@ -21,11 +21,12 @@ Load_Font_Error :: enum(i32) {
|
||||
}
|
||||
|
||||
Entry :: struct {
|
||||
parser_info : Parser_Font_Info,
|
||||
shaper_info : Shaper_Info,
|
||||
id : Font_ID,
|
||||
used : b32,
|
||||
curve_quality : f32,
|
||||
parser_info : Parser_Font_Info,
|
||||
shaper_info : Shaper_Info,
|
||||
id : Font_ID,
|
||||
used : b32,
|
||||
curve_quality : f32,
|
||||
// snap_glyph_pos :
|
||||
|
||||
ascent : f32,
|
||||
descent : f32,
|
||||
@ -98,26 +99,26 @@ Init_Atlas_Params :: struct {
|
||||
}
|
||||
|
||||
Init_Atlas_Params_Default :: Init_Atlas_Params {
|
||||
width = 4096,
|
||||
height = 2048,
|
||||
width = 4096 * 2,
|
||||
height = 2048 * 2,
|
||||
glyph_padding = 1,
|
||||
glyph_over_scalar = 1,
|
||||
|
||||
region_a = {
|
||||
width = 32,
|
||||
height = 32,
|
||||
width = 32 * 2,
|
||||
height = 32 * 2,
|
||||
},
|
||||
region_b = {
|
||||
width = 32,
|
||||
height = 64,
|
||||
width = 32 * 2,
|
||||
height = 64 * 2,
|
||||
},
|
||||
region_c = {
|
||||
width = 64,
|
||||
height = 64,
|
||||
width = 64 * 2,
|
||||
height = 64 * 2,
|
||||
},
|
||||
region_d = {
|
||||
width = 128,
|
||||
height = 128,
|
||||
width = 128 * 2,
|
||||
height = 128 * 2,
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,10 +225,10 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
error : Allocator_Error
|
||||
lru_init( & region.state, region.capacity.x * region.capacity.y )
|
||||
}
|
||||
init_atlas_region( & atlas.region_a, atlas_params, atlas_params.region_a, { 4, 2}, 1024 )
|
||||
init_atlas_region( & atlas.region_b, atlas_params, atlas_params.region_b, { 4, 2}, 512 )
|
||||
init_atlas_region( & atlas.region_c, atlas_params, atlas_params.region_c, { 4, 1}, 512 )
|
||||
init_atlas_region( & atlas.region_d, atlas_params, atlas_params.region_d, { 2, 1}, 256 )
|
||||
init_atlas_region( & atlas.region_a, atlas_params, atlas_params.region_a, { 4, 2}, 1024 * 4 )
|
||||
init_atlas_region( & atlas.region_b, atlas_params, atlas_params.region_b, { 4, 2}, 512 * 4 )
|
||||
init_atlas_region( & atlas.region_c, atlas_params, atlas_params.region_c, { 4, 1}, 512 * 4 )
|
||||
init_atlas_region( & atlas.region_d, atlas_params, atlas_params.region_d, { 2, 1}, 256 * 4 )
|
||||
|
||||
atlas.width = i32(atlas_params.width)
|
||||
atlas.height = i32(atlas_params.height)
|
||||
@ -494,10 +495,15 @@ configure_snap :: #force_inline proc( ctx : ^Context, snap_width, snap_height :
|
||||
ctx.snap_height = f32(snap_height)
|
||||
}
|
||||
|
||||
get_cursor_pos :: #force_inline proc( ctx : ^Context ) -> Vec2 { assert(ctx != nil); return ctx.cursor_pos }
|
||||
set_alpha_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.alpha_sharpen = scalar }
|
||||
set_px_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.px_scalar = scalar }
|
||||
set_colour :: #force_inline proc( ctx : ^Context, colour : Colour ) { assert(ctx != nil); ctx.colour = colour }
|
||||
get_cursor_pos :: #force_inline proc( ctx : ^Context ) -> Vec2 { assert(ctx != nil); return ctx.cursor_pos }
|
||||
set_alpha_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.alpha_sharpen = scalar }
|
||||
set_px_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.px_scalar = scalar }
|
||||
set_colour :: #force_inline proc( ctx : ^Context, colour : Colour ) { assert(ctx != nil); ctx.colour = colour }
|
||||
|
||||
set_snap_glyph_pos :: #force_inline proc( ctx : ^Context, should_snap : b32 ) {
|
||||
assert(ctx != nil)
|
||||
ctx.shaper_ctx.snap_glyph_position = should_snap
|
||||
}
|
||||
|
||||
draw_text :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32, position, scale : Vec2, text_utf8 : string )
|
||||
{
|
||||
@ -541,6 +547,46 @@ draw_text :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32,
|
||||
)
|
||||
}
|
||||
|
||||
draw_text_slice :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32, position, scale : Vec2, texts : []string )
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
assert( font >= 0 && int(font) < len(ctx.entries) )
|
||||
assert( len(texts) > 0 )
|
||||
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
ctx.cursor_pos = {}
|
||||
|
||||
position := position
|
||||
position.x = ceil(position.x * ctx.snap_width ) / ctx.snap_width
|
||||
position.y = ceil(position.y * ctx.snap_height) / ctx.snap_height
|
||||
|
||||
colour := ctx.colour
|
||||
colour.a = 1.0 + ctx.alpha_sharpen
|
||||
|
||||
font_scale := parser_scale( entry.parser_info, px_size )
|
||||
|
||||
px_upscale := px_size * ctx.px_scalar
|
||||
downscale := scale * (1 / ctx.px_scalar)
|
||||
font_scale_upscale := parser_scale( entry.parser_info, px_upscale )
|
||||
|
||||
shapes := make( []Shaped_Text, len(texts) )
|
||||
for str, id in texts {
|
||||
assert( len(str) > 0 )
|
||||
shape := shaper_shape_text_cached( str, & ctx.shaper_ctx, & ctx.shape_cache,
|
||||
font,
|
||||
entry,
|
||||
px_upscale,
|
||||
font_scale_upscale,
|
||||
shaper_shape_text_uncached_advanced
|
||||
)
|
||||
shapes[id] = shape
|
||||
}
|
||||
generate_shapes_draw_list(ctx, font, colour, entry, font_scale_upscale, position, scale, shapes )
|
||||
}
|
||||
|
||||
|
||||
// draw_text_no_snap :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32, position, scale : Vec2, text_utf8 : string )
|
||||
// {
|
||||
// profile(#procedure)
|
||||
|
@ -31,4 +31,3 @@ profile_begin :: #force_inline proc "contextless" ( name : string, loc := #calle
|
||||
profile_end :: #force_inline proc "contextless" () {
|
||||
spall._buffer_end( & Module_Context.ctx, & Module_Context.buffer)
|
||||
}
|
||||
|
||||
|
@ -18,10 +18,7 @@ import "core:strings"
|
||||
StringKey :: distinct u64
|
||||
RunesCached :: []rune
|
||||
|
||||
// TODO(Ed): There doesn't seem to be a need for caching the runes.
|
||||
// It seems like no one has had a bottleneck just iterating through the code points on demand when needed.
|
||||
// So we should problably scrap storing them that way.
|
||||
|
||||
// Note(Ed): No longer using for caching but could still be useful in the future
|
||||
StrRunesPair :: struct {
|
||||
str : string,
|
||||
runes : []rune,
|
||||
@ -29,9 +26,11 @@ StrRunesPair :: struct {
|
||||
to_str_runes_pair_via_string :: #force_inline proc ( content : string ) -> StrRunesPair { return { content, to_runes(content) } }
|
||||
to_str_runes_pair_via_runes :: #force_inline proc ( content : []rune ) -> StrRunesPair { return { to_string(content), content } }
|
||||
|
||||
StrCached :: string
|
||||
|
||||
StringCache :: struct {
|
||||
slab : Slab,
|
||||
table : HMapChained(StrRunesPair),
|
||||
table : HMapChained(StrCached),
|
||||
}
|
||||
|
||||
// This is the default string cache for the runtime module.
|
||||
@ -44,9 +43,9 @@ str_cache_init :: proc( table_allocator, slabs_allocator : Allocator ) -> (cache
|
||||
|
||||
policy : SlabPolicy
|
||||
policy_ptr := & policy
|
||||
// push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 8, alignment })
|
||||
// push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 16, alignment })
|
||||
// push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 32, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 8, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 16, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 32, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 640 * Kilobyte, 64, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 128, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 256, alignment })
|
||||
@ -71,7 +70,7 @@ str_cache_init :: proc( table_allocator, slabs_allocator : Allocator ) -> (cache
|
||||
cache.slab, alloc_error = slab_init( & policy, allocator = slabs_allocator, dbg_name = dbg_name )
|
||||
verify(alloc_error == .None, "Failed to initialize the string cache" )
|
||||
|
||||
cache.table, alloc_error = make( HMapChained(StrRunesPair), 1 * Kilo, table_allocator, dbg_name = dbg_name )
|
||||
cache.table, alloc_error = make( HMapChained(StrCached), 1 * Kilo, table_allocator, dbg_name = dbg_name )
|
||||
return
|
||||
}
|
||||
|
||||
@ -82,11 +81,11 @@ str_cache_reload :: #force_inline proc ( cache : ^StringCache, table_allocator,
|
||||
|
||||
str_cache_set_module_ctx :: #force_inline proc "contextless" ( cache : ^StringCache ) { Module_String_Cache = cache }
|
||||
str_intern_key :: #force_inline proc( content : string ) -> StringKey { return cast(StringKey) crc32( transmute([]byte) content ) }
|
||||
str_intern_lookup :: #force_inline proc( key : StringKey ) -> (^StrRunesPair) { return hmap_chained_get( Module_String_Cache.table, transmute(u64) key ) }
|
||||
str_intern_lookup :: #force_inline proc( key : StringKey ) -> (^StrCached) { return hmap_chained_get( Module_String_Cache.table, transmute(u64) key ) }
|
||||
|
||||
str_intern :: proc( content : string ) -> StrRunesPair
|
||||
str_intern :: #force_inline proc( content : string ) -> StrCached
|
||||
{
|
||||
// profile(#procedure)
|
||||
profile(#procedure)
|
||||
cache := Module_String_Cache
|
||||
key := str_intern_key(content)
|
||||
result := hmap_chained_get( cache.table, transmute(u64) key )
|
||||
@ -100,19 +99,14 @@ str_intern :: proc( content : string ) -> StrRunesPair
|
||||
|
||||
copy_non_overlapping( raw_data(str_mem), raw_data(content), length )
|
||||
|
||||
runes : []rune
|
||||
runes, alloc_error = to_runes( content, slab_allocator(cache.slab) )
|
||||
verify( alloc_error == .None, "String cache had a backing allocator error" )
|
||||
// slab_validate_pools( cache.slab.backing )
|
||||
|
||||
result, alloc_error = hmap_chained_set( cache.table, transmute(u64) key, StrRunesPair { transmute(string) str_mem, runes } )
|
||||
result, alloc_error = hmap_chained_set( cache.table, transmute(u64) key, transmute(StrCached) str_mem )
|
||||
verify( alloc_error == .None, "String cache had a backing allocator error" )
|
||||
// slab_validate_pools( cache.slab.backing )
|
||||
|
||||
return (result ^)
|
||||
}
|
||||
|
||||
str_intern_fmt :: #force_inline proc( format : string, args : ..any, allocator := context.allocator ) -> StrRunesPair {
|
||||
str_intern_fmt :: #force_inline proc( format : string, args : ..any, allocator := context.allocator ) -> StrCached {
|
||||
return str_intern(str_fmt(format, args, allocator = allocator))
|
||||
}
|
||||
|
||||
|
@ -137,10 +137,10 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
if ! dd_app_config.is_open do break app_config_closed
|
||||
ui_size_to_content_y( dd_app_config.vbox)
|
||||
|
||||
ui_settings_entry_inputbox :: proc( input_box : ^UI_TextInputBox, is_even : bool, label : string, setting_title : StrRunesPair, input_policy : UI_TextInput_Policy )
|
||||
ui_settings_entry_inputbox :: proc( input_box : ^UI_TextInputBox, is_even : bool, label : string, setting_title : StrCached, input_policy : UI_TextInput_Policy )
|
||||
{
|
||||
scope( theme_table_row(is_even))
|
||||
hb := ui_hbox(.Left_To_Right, str_intern_fmt("%v.hb", label).str); {
|
||||
hb := ui_hbox(.Left_To_Right, str_fmt("%v.hb", label)); {
|
||||
using hb
|
||||
|
||||
layout.size.min = {0, 25}
|
||||
@ -149,14 +149,14 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
}
|
||||
|
||||
scope(theme_text)
|
||||
title := ui_text(str_intern_fmt("%v.title", label).str, setting_title); {
|
||||
title := ui_text(str_fmt("%v.title", label), setting_title); {
|
||||
using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins.left = 10
|
||||
layout.font_size = 12
|
||||
}
|
||||
|
||||
ui_text_input_box( input_box, str_intern_fmt("%v.input_box", label).str, allocator = persistent_slab_allocator(), policy = input_policy )
|
||||
ui_text_input_box( input_box, str_fmt("%v.input_box", label), policy = input_policy, allocator = persistent_slab_allocator() )
|
||||
{
|
||||
using input_box
|
||||
layout.flags |= {.Fixed_Width}
|
||||
@ -357,7 +357,7 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
{
|
||||
ui_parent(dd_app_config.vbox)
|
||||
scope(theme_button)
|
||||
btn := ui_button(str_intern_fmt("settings_menu.cam_zoom_mode.%s.btn", entry).str)
|
||||
btn := ui_button(str_fmt("settings_menu.cam_zoom_mode.%s.btn", entry))
|
||||
{
|
||||
using btn
|
||||
layout.size.min = {100, 25}
|
||||
@ -368,7 +368,7 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
|
||||
ui_parent(btn)
|
||||
scope(theme_text)
|
||||
text_widget := ui_text(str_intern_fmt("settings_menu.cam_zoom_mode.%s.text", entry).str, str_intern_fmt("%s", entry))
|
||||
text_widget := ui_text(str_fmt("settings_menu.cam_zoom_mode.%s.text", entry), str_intern_fmt("%s", entry))
|
||||
}
|
||||
|
||||
if btn.pressed {
|
||||
@ -553,6 +553,35 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
append( & input_str, to_runes(str_fmt("%v", config.font_size_canvas_scalar)))
|
||||
}
|
||||
}
|
||||
|
||||
Text_Alpha_Sharpen:
|
||||
{
|
||||
ui_settings_entry_inputbox( & font_size_canvas_scalar_input, false, "settings_menu.font_size_canvas_scalar", str_intern("Font: Size Canvas Scalar"),
|
||||
UI_TextInput_Policy {
|
||||
digits_only = true,
|
||||
disallow_leading_zeros = false,
|
||||
disallow_decimal = false,
|
||||
digit_min = 0.001,
|
||||
digit_max = 10,
|
||||
max_length = 4,
|
||||
}
|
||||
)
|
||||
using font_size_canvas_scalar_input
|
||||
|
||||
if was_active
|
||||
{
|
||||
value, success := parse_f32(to_string(array_to_slice(input_str)))
|
||||
if success {
|
||||
value = clamp(value, 0.001, 9999.0)
|
||||
config.font_size_canvas_scalar = value
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clear( input_str )
|
||||
append( & input_str, to_runes(str_fmt("%v", config.font_size_canvas_scalar)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_vbox_end(vbox, compute_layout = false )
|
||||
|
@ -354,8 +354,8 @@ 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/sokol_gp.h", allocator = persistent_slab_allocator())
|
||||
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/ve_fontcache.h", 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() )
|
||||
@ -521,8 +521,6 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32
|
||||
context.allocator = frame_slab_allocator()
|
||||
context.temp_allocator = transient_allocator()
|
||||
|
||||
// rl.PollInputEvents()
|
||||
|
||||
config := & get_state().config
|
||||
debug := & get_state().debug
|
||||
|
||||
@ -530,6 +528,9 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32
|
||||
debug.draw_ui_padding_bounds = false
|
||||
debug.draw_ui_content_bounds = false
|
||||
|
||||
font_provider_set_alpha_sharpen(0.45)
|
||||
font_provider_set_snap_glyph_pos(true)
|
||||
|
||||
// config.engine_refresh_hz = 165
|
||||
|
||||
// config.color_theme = App_Thm_Light
|
||||
@ -550,7 +551,6 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32
|
||||
should_close |= update( host_delta_time_ms )
|
||||
render()
|
||||
|
||||
// rl.SwapScreenBuffer()
|
||||
return should_close
|
||||
}
|
||||
|
||||
|
@ -238,11 +238,11 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Worksapce Hot Box : %v", hot_box.label.str )
|
||||
debug_text("Worksapce Hot Box : %v", hot_box.label )
|
||||
debug_text("Workspace Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
}
|
||||
if active_box != nil{
|
||||
debug_text("Workspace Active Box: %v", active_box.label.str )
|
||||
debug_text("Workspace Active Box: %v", active_box.label )
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,11 +255,11 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Hot Box : %v", hot_box.label.str )
|
||||
debug_text("Hot Box : %v", hot_box.label )
|
||||
debug_text("Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
}
|
||||
if active_box != nil{
|
||||
debug_text("Active Box: %v", active_box.label.str )
|
||||
debug_text("Active Box: %v", active_box.label )
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,7 +590,7 @@ render_ui_via_box_list :: proc( box_list : []UI_RenderBoxInfo, text_list : []UI_
|
||||
box_layer_done : b32 = false
|
||||
for box_id < cast(i32) len(box_list) && ! box_layer_done
|
||||
{
|
||||
profile("GP_Render")
|
||||
// profile("GP_Render")
|
||||
box_layer_done = b32(box_id > 0) && box_list[ box_id - 1 ].layer_signal
|
||||
|
||||
entry := box_list[box_id]
|
||||
@ -629,7 +629,7 @@ render_ui_via_box_list :: proc( box_list : []UI_RenderBoxInfo, text_list : []UI_
|
||||
}
|
||||
|
||||
if shape_enqueued {
|
||||
profile("render ui box_layer")
|
||||
// profile("render ui box_layer")
|
||||
render_flush_gp()
|
||||
shape_enqueued = false
|
||||
}
|
||||
@ -638,7 +638,7 @@ render_ui_via_box_list :: proc( box_list : []UI_RenderBoxInfo, text_list : []UI_
|
||||
text_layer_done : b32 = false
|
||||
for text_id < cast(i32) len(text_list) && ! text_layer_done
|
||||
{
|
||||
profile("Text_Render")
|
||||
// profile("Text_Render")
|
||||
entry := text_list[text_id]
|
||||
font := entry.font.key != 0 ? entry.font : default_font
|
||||
|
||||
|
@ -46,14 +46,14 @@ font_provider_startup :: proc( ctx : ^FontProviderContext )
|
||||
verify( error == AllocatorError.None, "Failed to allocate font_cache" )
|
||||
|
||||
ve.startup( & ve_ctx, .STB_TrueType, allocator = persistent_slab_allocator() )
|
||||
ve_ctx.glyph_buffer.over_sample = { 4,4 }
|
||||
// ve_ctx.glyph_buffer.over_sample = { 4,4 }
|
||||
log("VEFontCached initialized")
|
||||
font_provider_setup_sokol_gfx_objects( & render, ve_ctx )
|
||||
}
|
||||
|
||||
font_provider_reload :: proc( ctx : ^FontProviderContext )
|
||||
{
|
||||
ctx.ve_ctx.glyph_buffer.over_sample = { 4,4 } * 1.0
|
||||
// ctx.ve_ctx.glyph_buffer.over_sample = { 4,4 } * 2
|
||||
hmap_chained_reload( ctx.font_cache, persistent_allocator())
|
||||
ve.hot_reload( & ctx.ve_ctx, persistent_slab_allocator() )
|
||||
ve.clear_atlas_region_caches(& ctx.ve_ctx)
|
||||
@ -116,10 +116,18 @@ font_load :: proc(path_file : string,
|
||||
return fid
|
||||
}
|
||||
|
||||
font_provider_set_alpha_sharpen :: #force_inline proc( scalar : f32 ) {
|
||||
ve.set_alpha_scalar( & get_state().font_provider_ctx.ve_ctx, scalar )
|
||||
}
|
||||
|
||||
font_provider_set_px_scalar :: #force_inline proc( scalar : f32 ) {
|
||||
ve.set_px_scalar( & get_state().font_provider_ctx.ve_ctx, scalar )
|
||||
}
|
||||
|
||||
font_provider_set_snap_glyph_pos :: #force_inline proc( should_snap : b32 ) {
|
||||
ve.set_snap_glyph_pos( & get_state().font_provider_ctx.ve_ctx, should_snap )
|
||||
}
|
||||
|
||||
Font_Use_Default_Size :: f32(0.0)
|
||||
|
||||
font_provider_resolve_draw_id :: #force_inline proc( id : FontID, size := Font_Use_Default_Size ) -> (ve_id :ve.Font_ID, resolved_size : i32)
|
||||
|
@ -172,8 +172,8 @@ font_provider_setup_sokol_gfx_objects :: proc( ctx : ^VE_RenderData, ve_ctx : ve
|
||||
mipmap_filter = Filter.NEAREST,
|
||||
wrap_u = .CLAMP_TO_EDGE,
|
||||
wrap_v = .CLAMP_TO_EDGE,
|
||||
min_lod = -1000.0,
|
||||
max_lod = 1000.0,
|
||||
min_lod = -1.0,
|
||||
max_lod = 1.0,
|
||||
border_color = BorderColor.OPAQUE_BLACK,
|
||||
compare = .NEVER,
|
||||
max_anisotropy = 1,
|
||||
@ -307,14 +307,14 @@ font_provider_setup_sokol_gfx_objects :: proc( ctx : ^VE_RenderData, ve_ctx : ve
|
||||
atlas_rt_sampler = sokol_gfx.make_sampler( SamplerDescription {
|
||||
min_filter = Image_Filter,
|
||||
mag_filter = Image_Filter,
|
||||
mipmap_filter = Filter.LINEAR,
|
||||
mipmap_filter = Filter.NEAREST,
|
||||
wrap_u = .CLAMP_TO_EDGE,
|
||||
wrap_v = .CLAMP_TO_EDGE,
|
||||
min_lod = -1000.0,
|
||||
max_lod = 1000.0,
|
||||
min_lod = -1.0,
|
||||
max_lod = 1.0,
|
||||
border_color = BorderColor.OPAQUE_BLACK,
|
||||
compare = .NEVER,
|
||||
max_anisotropy = 16,
|
||||
max_anisotropy = 1,
|
||||
})
|
||||
verify( sokol_gfx.query_sampler_state( atlas_rt_sampler) < ResourceState.FAILED, "Failed to make atlas_rt_sampler" )
|
||||
|
||||
|
@ -305,8 +305,8 @@ import "codebase:grime"
|
||||
to_bytes :: grime.to_bytes
|
||||
|
||||
// strings
|
||||
StrRunesPair :: grime.StrRunesPair
|
||||
StringCache :: grime.StringCache
|
||||
StrCached :: grime.StrCached
|
||||
StringCache :: grime.StringCache
|
||||
|
||||
str_cache_init :: grime.str_cache_init
|
||||
str_cache_reload :: grime.str_cache_reload
|
||||
|
@ -63,7 +63,7 @@ PWS_LexResult :: struct {
|
||||
PWS_Token :: struct {
|
||||
type : PWS_TokenType,
|
||||
line, column : u32,
|
||||
content : StrRunesPair,
|
||||
content : StrCached,
|
||||
}
|
||||
|
||||
PWS_AST_Type :: enum u32 {
|
||||
@ -80,7 +80,7 @@ PWS_AST :: struct {
|
||||
type : PWS_AST_Type,
|
||||
|
||||
line, column : u32,
|
||||
content : StrRunesPair,
|
||||
content : StrCached,
|
||||
}
|
||||
|
||||
PWS_ParseError :: struct {
|
||||
|
@ -15,8 +15,8 @@ ProjectConfig :: struct {
|
||||
}
|
||||
|
||||
Project :: struct {
|
||||
path : StrRunesPair,
|
||||
name : StrRunesPair,
|
||||
path : StrCached,
|
||||
name : StrCached,
|
||||
|
||||
config : ProjectConfig,
|
||||
codebase : CodeBase,
|
||||
|
@ -163,12 +163,12 @@ project_save :: proc( project : ^ Project, archive : ^ ArchiveData = nil )
|
||||
}
|
||||
project_serialize( project, archive )
|
||||
|
||||
if ! os.is_dir( project.path.str ) {
|
||||
os.make_directory( project.path.str )
|
||||
verify( cast(b32) os.is_dir( project.path.str ), "Failed to create project path for saving" )
|
||||
if ! os.is_dir( project.path) {
|
||||
os.make_directory( project.path )
|
||||
verify( cast(b32) os.is_dir( project.path ), "Failed to create project path for saving" )
|
||||
}
|
||||
|
||||
os.write_entire_file( str_tmp_from_any( project.path.str, project.name.str, ".sectr_proj", sep = ""), archive.data )
|
||||
os.write_entire_file( str_tmp_from_any( project.path, project.name, ".sectr_proj", sep = ""), archive.data )
|
||||
}
|
||||
|
||||
project_load :: proc( path : string, project : ^ Project, archive : ^ ArchiveData = nil )
|
||||
|
@ -7,7 +7,7 @@ or frame tiling towards the application's screenspace.
|
||||
package sectr
|
||||
|
||||
Workspace :: struct {
|
||||
name : StrRunesPair,
|
||||
name : StrCached,
|
||||
|
||||
cam : Camera,
|
||||
zoom_target : f32,
|
||||
|
@ -15,34 +15,36 @@ layout(binding = 0) uniform texture2D ve_blit_atlas_src_texture;
|
||||
layout(binding = 0) uniform sampler ve_blit_atlas_src_sampler;
|
||||
|
||||
layout(binding = 0) uniform ve_blit_atlas_fs_params {
|
||||
int region;
|
||||
Vec2 glyph_buffer_size;
|
||||
f32 over_sample;
|
||||
int region;
|
||||
};
|
||||
|
||||
float down_sample( vec2 uv, vec2 texture_size )
|
||||
float down_sample_( vec2 uv, vec2 texture_size )
|
||||
{
|
||||
float down_sample_scale = 1.0f / 4.0f;
|
||||
float down_sample = 1.0f / over_sample;
|
||||
|
||||
float value =
|
||||
texture(sampler2D( ve_blit_atlas_src_texture, ve_blit_atlas_src_sampler ), uv + vec2( 0.0f, 0.0f ) * texture_size ).x * down_sample_scale
|
||||
+ texture(sampler2D( ve_blit_atlas_src_texture, ve_blit_atlas_src_sampler ), uv + vec2( 0.0f, 1.0f ) * texture_size ).x * down_sample_scale
|
||||
+ texture(sampler2D( ve_blit_atlas_src_texture, ve_blit_atlas_src_sampler ), uv + vec2( 1.0f, 0.0f ) * texture_size ).x * down_sample_scale
|
||||
+ texture(sampler2D( ve_blit_atlas_src_texture, ve_blit_atlas_src_sampler ), uv + vec2( 1.0f, 1.0f ) * texture_size ).x * down_sample_scale;
|
||||
texture(sampler2D( ve_blit_atlas_src_texture, ve_blit_atlas_src_sampler ), uv + vec2( 0.0f, 0.0f ) * glyph_buffer_size ).x * down_sample
|
||||
+ texture(sampler2D( ve_blit_atlas_src_texture, ve_blit_atlas_src_sampler ), uv + vec2( 0.0f, 1.0f ) * glyph_buffer_size ).x * down_sample
|
||||
+ texture(sampler2D( ve_blit_atlas_src_texture, ve_blit_atlas_src_sampler ), uv + vec2( 1.0f, 0.0f ) * glyph_buffer_size ).x * down_sample
|
||||
+ texture(sampler2D( ve_blit_atlas_src_texture, ve_blit_atlas_src_sampler ), uv + vec2( 1.0f, 1.0f ) * glyph_buffer_size ).x * down_sample;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// TODO(Ed): The original author made these consts, I want to instead expose as uniforms...
|
||||
const vec2 texture_size = 1.0f / vec2( 2048.0f, 512.0f ); // VEFontCache.Context.buffer_width/buffer_height
|
||||
if ( region == 0 || region == 1 || region == 2 )
|
||||
{
|
||||
float down_sample_scale = 1.0f / 4.0f;
|
||||
float down_sample = 1.0f / over_sample;
|
||||
|
||||
float alpha =
|
||||
down_sample( uv + vec2( -1.0f, -1.5f ) * texture_size, texture_size ) * down_sample_scale
|
||||
+ down_sample( uv + vec2( 0.5f, -1.5f ) * texture_size, texture_size ) * down_sample_scale
|
||||
+ down_sample( uv + vec2( -1.5f, 0.5f ) * texture_size, texture_size ) * down_sample_scale
|
||||
+ down_sample( uv + vec2( 0.5f, 0.5f ) * texture_size, texture_size ) * down_sample_scale;
|
||||
down_sample( uv + vec2( -1.0f, -1.5f ) * texture_size, glyph_buffer_size ) * down_sample
|
||||
+ down_sample( uv + vec2( 0.5f, -1.5f ) * texture_size, glyph_buffer_size ) * down_sample
|
||||
+ down_sample( uv + vec2( -1.5f, 0.5f ) * texture_size, glyph_buffer_size ) * down_sample
|
||||
+ down_sample( uv + vec2( 0.5f, 0.5f ) * texture_size, glyph_buffer_size ) * down_sample;
|
||||
frag_color = vec4( 1.0f, 1.0f, 1.0f, alpha );
|
||||
}
|
||||
else
|
||||
|
@ -23,25 +23,24 @@ layout(binding = 0) uniform texture2D ve_draw_text_src_texture;
|
||||
layout(binding = 0) uniform sampler ve_draw_text_src_sampler;
|
||||
|
||||
layout(binding = 0) uniform ve_draw_text_fs_params {
|
||||
int down_sample;
|
||||
Vec2 glyph_buffer_size;
|
||||
f32 over_sample;
|
||||
vec4 colour;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
float alpha = texture(sampler2D( ve_draw_text_src_texture, ve_draw_text_src_sampler ), uv ).x;
|
||||
if ( down_sample == 1 )
|
||||
{
|
||||
// TODO(Ed): The original author made these consts, I want to instead expose as uniforms...
|
||||
const vec2 texture_size = 1.0f / vec2( 2048.0f, 512.0f ); // VEFontCache.Context.buffer_width/buffer_height
|
||||
const float down_sample_scale = 1.0f / 4.0f;
|
||||
|
||||
alpha =
|
||||
(texture(sampler2D( ve_draw_text_src_texture, ve_draw_text_src_sampler), uv + vec2( -0.5f, -0.5f) * texture_size ).x * down_sample_scale)
|
||||
+ (texture(sampler2D( ve_draw_text_src_texture, ve_draw_text_src_sampler), uv + vec2( -0.5f, 0.5f) * texture_size ).x * down_sample_scale)
|
||||
+ (texture(sampler2D( ve_draw_text_src_texture, ve_draw_text_src_sampler), uv + vec2( 0.5f, -0.5f) * texture_size ).x * down_sample_scale)
|
||||
+ (texture(sampler2D( ve_draw_text_src_texture, ve_draw_text_src_sampler), uv + vec2( 0.5f, 0.5f) * texture_size ).x * down_sample_scale);
|
||||
}
|
||||
const vec2 texture_size = 1.0f / ;
|
||||
const float down_sample = 1.0f / over_sample;
|
||||
|
||||
alpha =
|
||||
(texture(sampler2D( ve_draw_text_src_texture, ve_draw_text_src_sampler), uv + vec2( -0.5f, -0.5f) * glyph_buffer_size ).x * down_sample)
|
||||
+ (texture(sampler2D( ve_draw_text_src_texture, ve_draw_text_src_sampler), uv + vec2( -0.5f, 0.5f) * glyph_buffer_size ).x * down_sample)
|
||||
+ (texture(sampler2D( ve_draw_text_src_texture, ve_draw_text_src_sampler), uv + vec2( 0.5f, -0.5f) * glyph_buffer_size ).x * down_sample)
|
||||
+ (texture(sampler2D( ve_draw_text_src_texture, ve_draw_text_src_sampler), uv + vec2( 0.5f, 0.5f) * glyph_buffer_size ).x * down_sample);
|
||||
|
||||
frag_color = vec4( colour.xyz, colour.a * alpha );
|
||||
}
|
||||
@end
|
||||
|
@ -237,7 +237,7 @@ ui_graph_build_begin :: proc( ui : ^ UI_State, bounds : Vec2 = {} )
|
||||
}
|
||||
|
||||
ui.built_box_count = 0
|
||||
root = ui_box_make( {}, str_intern(str_fmt("%s: root#001", ui == & state.screen_ui ? "Screen" : "Workspace" )).str)
|
||||
root = ui_box_make( {}, str_intern(str_fmt("%s: root#001", ui == & state.screen_ui ? "Screen" : "Workspace" )))
|
||||
if ui == & state.screen_ui {
|
||||
root.layout.size = range2(Vec2(state.app_window.extent) * 2, {})
|
||||
}
|
||||
@ -283,7 +283,8 @@ ui_graph_build_end :: proc( ui : ^UI_State )
|
||||
|
||||
if ! current.computed.fresh
|
||||
{
|
||||
if len(current.text.str) > 0 {
|
||||
if len(current.text) > 0 {
|
||||
profile("text shape")
|
||||
// app_window := get_state().app_window
|
||||
// screen_extent := app_window.extent
|
||||
// screen_size := screen_extent * 2
|
||||
@ -293,7 +294,7 @@ ui_graph_build_end :: proc( ui : ^UI_State )
|
||||
|
||||
// over_sample : f32 = f32(get_state().config.font_size_canvas_scalar)
|
||||
|
||||
current.computed.text_shape = shape_text_cached( current.text.str, current.style.font, current.layout.font_size, 1.0 )
|
||||
current.computed.text_shape = shape_text_cached( current.text, current.style.font, current.layout.font_size, 1.0 )
|
||||
}
|
||||
ui_box_compute_layout( current )
|
||||
}
|
||||
@ -302,6 +303,8 @@ ui_graph_build_end :: proc( ui : ^UI_State )
|
||||
continue
|
||||
}
|
||||
|
||||
profile("render queue resolution")
|
||||
|
||||
different_ancestory := b8(current.ancestors != previous_layer)
|
||||
|
||||
entry_box := UI_RenderBoxInfo {
|
||||
@ -318,7 +321,7 @@ ui_graph_build_end :: proc( ui : ^UI_State )
|
||||
// if len(current.text.str) > 0
|
||||
// {
|
||||
entry_text := UI_RenderTextInfo {
|
||||
text = current.text.str,
|
||||
text = current.text,
|
||||
shape = current.computed.text_shape,
|
||||
position = current.computed.text_pos,
|
||||
color = current.style.text_color,
|
||||
|
@ -22,8 +22,8 @@ UI_NavLinks :: struct {
|
||||
UI_Box :: struct {
|
||||
// Cache ID
|
||||
key : UI_Key,
|
||||
label : StrRunesPair,
|
||||
text : StrRunesPair,
|
||||
label : StrCached,
|
||||
text : StrCached,
|
||||
|
||||
// Regenerated per frame.
|
||||
nav : UI_NavLinks,
|
||||
@ -67,7 +67,7 @@ ui_box_from_key :: #force_inline proc ( cache : ^HMapChained(UI_Box), key : UI_K
|
||||
|
||||
ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
|
||||
{
|
||||
// profile(#procedure)
|
||||
profile(#procedure)
|
||||
using ui := get_state().ui_context
|
||||
key := ui_key_from_string( label )
|
||||
|
||||
|
@ -194,21 +194,21 @@ ui_layout_pop :: #force_inline proc() { pop( &
|
||||
|
||||
ui_set_layout :: #force_inline proc( layout : UI_Layout, preset : UI_StylePreset ) { stack_peek_ref( & get_state().ui_context.layout_combo_stack).array[preset] = layout }
|
||||
|
||||
ui_size_to_content_xy :: proc ( box : ^UI_Box) {
|
||||
ui_size_to_content_xy :: #force_inline proc ( box : ^UI_Box) {
|
||||
using box
|
||||
children_bounds := ui_compute_children_overall_bounds(box)
|
||||
layout.size.min = size_range2(children_bounds)
|
||||
layout.flags |= { .Fixed_Width, .Fixed_Height }
|
||||
}
|
||||
|
||||
ui_size_to_content_x :: proc ( box : ^UI_Box) {
|
||||
ui_size_to_content_x :: #force_inline proc ( box : ^UI_Box) {
|
||||
using box
|
||||
children_bounds := ui_compute_children_overall_bounds(box)
|
||||
layout.size.min.x = size_range2(children_bounds).x
|
||||
layout.flags |= { .Fixed_Width }
|
||||
}
|
||||
|
||||
ui_size_to_content_y :: proc ( box : ^UI_Box) {
|
||||
ui_size_to_content_y :: #force_inline proc ( box : ^UI_Box) {
|
||||
using box
|
||||
children_bounds := ui_compute_children_overall_bounds(box)
|
||||
layout.size.min.y = size_range2(children_bounds).y
|
||||
|
@ -71,7 +71,7 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
|
||||
adjusted_size.y = max( adjusted_max_size_y, layout.size.min.y)
|
||||
|
||||
text_size : Vec2
|
||||
if len(box.text.str) > 0
|
||||
if len(box.text) > 0
|
||||
{
|
||||
text_size = computed.text_shape.size
|
||||
// if layout.font_size == computed.text_size.y {
|
||||
@ -187,7 +187,7 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
|
||||
computed.content = content_bounds
|
||||
|
||||
// 8. Text position & size
|
||||
if len(box.text.str) > 0
|
||||
if len(box.text) > 0
|
||||
{
|
||||
ascent, descent, line_gap := get_font_vertical_metrics(style.font, layout.font_size)
|
||||
|
||||
|
@ -30,7 +30,7 @@ UI_Signal :: struct {
|
||||
|
||||
ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas := true ) -> UI_Signal
|
||||
{
|
||||
// profile(#procedure)
|
||||
profile(#procedure)
|
||||
ui := get_state().ui_context
|
||||
input := get_state().input
|
||||
|
||||
|
@ -22,7 +22,7 @@ ui_floating_startup :: proc( self : ^UI_FloatingManager, build_queue_cap, tracke
|
||||
error : AllocatorError
|
||||
|
||||
queue_dbg_name := str_intern(str_fmt("%s: build_queue", dbg_name))
|
||||
self.build_queue, error = make( Array(UI_Floating), build_queue_cap, dbg_name = queue_dbg_name.str, allocator = allocator )
|
||||
self.build_queue, error = make( Array(UI_Floating), build_queue_cap, dbg_name = queue_dbg_name, allocator = allocator )
|
||||
if error != AllocatorError.None
|
||||
{
|
||||
ensure(false, "Failed to allocate the build_queue")
|
||||
|
@ -61,8 +61,8 @@ test_draggable :: proc()
|
||||
draggable.layout.pos = debug.draggable_box_pos
|
||||
draggable.layout.size.min = debug.draggable_box_size
|
||||
|
||||
draggable.text = { str_fmt("%v", debug.draggable_box_pos), {} }
|
||||
draggable.text.runes = to_runes(draggable.text.str)
|
||||
draggable.text = str_intern_fmt("%v", debug.draggable_box_pos)
|
||||
// draggable.text.runes = to_runes(draggable.text)
|
||||
}
|
||||
|
||||
test_parenting :: proc( default_layout : ^UI_Layout, frame_style_default : ^UI_Style )
|
||||
@ -195,6 +195,9 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
|
||||
label_id := 0
|
||||
|
||||
builder : StringBuilder
|
||||
str.builder_init_len_cap( & builder, len = 0, cap = 16 * Kilobyte )
|
||||
|
||||
line_id := 0
|
||||
for line in array_to_slice( debug.lorem_parse.lines )
|
||||
{
|
||||
@ -205,11 +208,17 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
profile("line")
|
||||
|
||||
ui_layout( text_layout )
|
||||
line_hbox := ui_widget(str_fmt( "line %v", line_id ), {.Mouse_Clickable})
|
||||
|
||||
if line_hbox.key == ui.hot && false
|
||||
profile_begin("label fmt")
|
||||
str.builder_reset( & builder)
|
||||
label := str_fmt_builder( & builder, "line %d", line_id )
|
||||
profile_end()
|
||||
|
||||
line_hbox := ui_widget(label, {.Mouse_Clickable})
|
||||
|
||||
if false && line_hbox.key == ui.hot
|
||||
{
|
||||
line_hbox.text = StrRunesPair {}
|
||||
line_hbox.text = StrCached {}
|
||||
ui_parent(line_hbox)
|
||||
|
||||
chunk_layout := text_layout
|
||||
@ -230,33 +239,34 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
#partial switch head.type
|
||||
{
|
||||
case .Visible:
|
||||
label := str_intern( str_fmt( "%v %v", head.content.str, label_id ))
|
||||
widget = ui_text( label.str, head.content )
|
||||
label := str_fmt( "%v %v", head.content, label_id )
|
||||
widget = ui_text( label, head.content )
|
||||
label_id += 1
|
||||
|
||||
chunk_layout.pos.x += size_range2( widget.computed.bounds ).x
|
||||
|
||||
case .Spaces:
|
||||
label := str_intern( str_fmt( "%v %v", "space", label_id ))
|
||||
widget = ui_text_spaces( label.str )
|
||||
label := str_fmt( "%v %v", "space", label_id )
|
||||
widget = ui_text_spaces( label )
|
||||
label_id += 1
|
||||
|
||||
for idx in 1 ..< len( head.content.runes )
|
||||
{
|
||||
// for idx in 1 ..< len( head.content.runes )
|
||||
// {
|
||||
// TODO(Ed): VIRTUAL WHITESPACE
|
||||
// widget.style.layout.size.x += range2_size( widget.computed.bounds )
|
||||
}
|
||||
// }
|
||||
chunk_layout.pos.x += size_range2( widget.computed.bounds ).x
|
||||
|
||||
case .Tabs:
|
||||
label := str_intern( str_fmt( "%v %v", "tab", label_id ))
|
||||
widget = ui_text_tabs( label.str )
|
||||
label := str_fmt( "%v %v", "tab", label_id )
|
||||
widget = ui_text_tabs( label )
|
||||
label_id += 1
|
||||
|
||||
for idx in 1 ..< len( head.content.runes )
|
||||
{
|
||||
// for idx in 1 ..< len( head.content.runes )
|
||||
// {
|
||||
// TODO(Ed): VIRTUAL WHITESPACE
|
||||
// widget.style.layout.size.x += range2_size( widget.computed.bounds )
|
||||
}
|
||||
// }
|
||||
chunk_layout.pos.x += size_range2( widget.computed.bounds ).x
|
||||
}
|
||||
|
||||
@ -268,30 +278,31 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
}
|
||||
else
|
||||
{
|
||||
builder_backing : [16 * Kilobyte] byte
|
||||
builder := str.builder_from_bytes( builder_backing[:] )
|
||||
profile("line (single-box)")
|
||||
|
||||
line_hbox.layout.flags |= { .Size_To_Text }
|
||||
|
||||
str.builder_reset( & builder)
|
||||
head := line.first.next
|
||||
for ; head != nil;
|
||||
{
|
||||
str.write_string( & builder, head.content.str )
|
||||
profile("write ast node")
|
||||
str.write_string( & builder, head.content )
|
||||
head = head.next
|
||||
}
|
||||
|
||||
profile("intern")
|
||||
line_hbox.text = str_intern( to_string( builder ) )
|
||||
// if len(line_hbox.text.str) == 0 {
|
||||
// line_hbox.text = str_intern( " " )
|
||||
// }
|
||||
}
|
||||
|
||||
if len(line_hbox.text.str) > 0 {
|
||||
if len(line_hbox.text) > 0 {
|
||||
profile("append actual")
|
||||
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
|
||||
}
|
||||
else {
|
||||
profile("end")
|
||||
widget := & widgets.data[ widgets.num - 1 ]
|
||||
if widget.box != nil {
|
||||
text_layout.pos.y -= size_range2( widget.computed.bounds ).y
|
||||
|
@ -11,14 +11,14 @@ UI_Widget :: struct {
|
||||
using signal : UI_Signal,
|
||||
}
|
||||
|
||||
ui_widget :: proc( label : string, flags : UI_BoxFlags ) -> (widget : UI_Widget)
|
||||
ui_widget :: #force_inline proc( label : string, flags : UI_BoxFlags ) -> (widget : UI_Widget)
|
||||
{
|
||||
widget.box = ui_box_make( flags, label )
|
||||
widget.signal = ui_signal_from_box( widget.box )
|
||||
return
|
||||
}
|
||||
|
||||
ui_button :: proc( label : string, flags : UI_BoxFlags = {} ) -> (btn : UI_Widget)
|
||||
ui_button :: #force_inline proc( label : string, flags : UI_BoxFlags = {} ) -> (btn : UI_Widget)
|
||||
{
|
||||
btn_flags := UI_BoxFlags { .Mouse_Clickable }
|
||||
btn.box = ui_box_make( btn_flags | flags, label )
|
||||
@ -36,7 +36,7 @@ UI_DropDown :: struct {
|
||||
}
|
||||
|
||||
@(deferred_out = ui_drop_down_end_auto)
|
||||
ui_drop_down :: proc( drop_down : ^UI_DropDown, label : string, title_text : StrRunesPair,
|
||||
ui_drop_down :: proc( drop_down : ^UI_DropDown, label : string, title_text : StrCached,
|
||||
direction := UI_LayoutDirection_Y.Top_To_Bottom,
|
||||
btn_flags := UI_BoxFlags{},
|
||||
vb_flags := UI_BoxFlags{},
|
||||
@ -54,7 +54,7 @@ ui_drop_down :: proc( drop_down : ^UI_DropDown, label : string, title_text : Str
|
||||
}
|
||||
|
||||
// Its assumed that the drop down has a vertical box parent already pushed
|
||||
ui_drop_down_begin :: proc( drop_down : ^UI_DropDown, label : string, title_text : StrRunesPair,
|
||||
ui_drop_down_begin :: proc( drop_down : ^UI_DropDown, label : string, title_text : StrCached,
|
||||
direction := UI_LayoutDirection_Y.Top_To_Bottom,
|
||||
btn_flags := UI_BoxFlags{},
|
||||
vb_flags := UI_BoxFlags{},
|
||||
@ -68,7 +68,7 @@ ui_drop_down_begin :: proc( drop_down : ^UI_DropDown, label : string, title_text
|
||||
if btn_theme == nil do push(theme_drop_down_btn)
|
||||
else do push(btn_theme ^)
|
||||
defer ui_theme_pop()
|
||||
btn = ui_button( str_intern_fmt("%s.btn", label).str );
|
||||
btn = ui_button( str_fmt("%s.btn", label) );
|
||||
{
|
||||
btn.layout.padding.left = 4
|
||||
ui_parent(btn)
|
||||
@ -76,7 +76,7 @@ ui_drop_down_begin :: proc( drop_down : ^UI_DropDown, label : string, title_text
|
||||
if title_theme == nil do push(theme_text)
|
||||
else do push(title_theme ^)
|
||||
defer ui_theme_pop()
|
||||
title = ui_text( str_intern_fmt("%s.btn.title", label).str, title_text)
|
||||
title = ui_text( str_fmt("%s.btn.title", label), title_text)
|
||||
}
|
||||
|
||||
if btn.pressed {
|
||||
@ -91,7 +91,7 @@ ui_drop_down_begin :: proc( drop_down : ^UI_DropDown, label : string, title_text
|
||||
if vb_parent != nil {
|
||||
ui_parent_push(vb_parent)
|
||||
}
|
||||
vbox = ui_vbox_begin( direction, str_intern_fmt("%v.vbox", label).str, flags = {.Mouse_Clickable}, compute_layout = vb_compute_layout )
|
||||
vbox = ui_vbox_begin( direction, str_fmt("%v.vbox", label), flags = {.Mouse_Clickable}, compute_layout = vb_compute_layout )
|
||||
vbox.layout.anchor.ratio.y = 1.0
|
||||
|
||||
if vb_parent != nil {
|
||||
@ -328,7 +328,7 @@ ui_resizable_handles :: #force_no_inline proc( parent : ^UI_Widget, pos : ^Vec2,
|
||||
|
||||
name :: proc( label : string ) -> string {
|
||||
parent_label := (transmute(^string) context.user_ptr) ^
|
||||
return str_intern(str_fmt("%v.%v", parent_label, label )).str
|
||||
return str_fmt("%v.%v", parent_label, label )
|
||||
}
|
||||
context.user_ptr = & parent.label
|
||||
|
||||
@ -523,9 +523,9 @@ ui_scroll_box :: proc( label : string, flags : UI_BoxFlags ) -> (scroll_box : UI
|
||||
}
|
||||
|
||||
#region("Text")
|
||||
ui_text :: proc( label : string, content : StrRunesPair, flags : UI_BoxFlags = {} ) -> UI_Widget
|
||||
ui_text :: #force_inline proc( label : string, content : StrCached, flags : UI_BoxFlags = {} ) -> UI_Widget
|
||||
{
|
||||
// profile(#procedure)
|
||||
profile(#procedure)
|
||||
state := get_state(); using state
|
||||
|
||||
box := ui_box_make( flags, label )
|
||||
@ -535,9 +535,9 @@ ui_text :: proc( label : string, content : StrRunesPair, flags : UI_BoxFlags = {
|
||||
return { box, signal }
|
||||
}
|
||||
|
||||
ui_text_spaces :: proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget
|
||||
ui_text_spaces :: #force_inline proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget
|
||||
{
|
||||
// profile(#procedure)
|
||||
profile(#procedure)
|
||||
state := get_state(); using state
|
||||
|
||||
// TODO(Ed) : Move this somwhere in state.
|
||||
@ -550,9 +550,9 @@ ui_text_spaces :: proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget
|
||||
return { box, signal }
|
||||
}
|
||||
|
||||
ui_text_tabs :: proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget
|
||||
ui_text_tabs :: #force_inline proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget
|
||||
{
|
||||
// profile(#procedure)
|
||||
profile(#procedure)
|
||||
state := get_state(); using state
|
||||
|
||||
// TODO(Ed) : Move this somwhere in state.
|
||||
@ -595,8 +595,8 @@ ui_text_input_box_reload :: #force_inline proc ( text_box : ^UI_TextInputBox, al
|
||||
|
||||
ui_text_input_box :: proc( text_input_box : ^UI_TextInputBox, label : string,
|
||||
flags : UI_BoxFlags = {.Mouse_Clickable, .Focusable, .Click_To_Focus},
|
||||
allocator := context.allocator,
|
||||
policy : UI_TextInput_Policy = {}
|
||||
policy : UI_TextInput_Policy = {},
|
||||
allocator : Allocator,
|
||||
)
|
||||
{
|
||||
// state := get_state()
|
||||
@ -619,6 +619,7 @@ ui_text_input_box :: proc( text_input_box : ^UI_TextInputBox, label : string,
|
||||
input_str, error = make( Array(rune), Kilo, allocator )
|
||||
ensure(error == AllocatorError.None, "Failed to allocate array for input_str of input_box")
|
||||
}
|
||||
input_str.backing = allocator // Always assign allocator for hot-reload purposes
|
||||
|
||||
if active
|
||||
{
|
||||
@ -706,19 +707,19 @@ ui_text_input_box :: proc( text_input_box : ^UI_TextInputBox, label : string,
|
||||
ui_parent(text_input_box)
|
||||
name :: proc( label : string ) -> string {
|
||||
parent_label := (transmute(^string) context.user_ptr) ^
|
||||
return str_intern(str_fmt("%v: %v", parent_label, label )).str
|
||||
return str_intern(str_fmt("%v: %v", parent_label, label ))
|
||||
}
|
||||
context.user_ptr = & parent.label
|
||||
|
||||
// TODO(Ed): Allow for left and center alignment of text
|
||||
value_txt : UI_Widget; {
|
||||
scope(theme_text)
|
||||
value_txt = ui_text(name("input_str"), to_str_runes_pair(array_to_slice(input_str)))
|
||||
value_txt = ui_text(name("input_str"), str_intern(to_string(array_to_slice(input_str))))
|
||||
using value_txt
|
||||
layout.alignment = {0.0, 0.0}
|
||||
layout.text_alignment = {1.0, 0.5}
|
||||
layout.anchor.left = 0.0
|
||||
layout.size.min = cast(Vec2) measure_text_size( text.str, style.font, layout.font_size, 0 )
|
||||
layout.size.min = cast(Vec2) measure_text_size( text, style.font, layout.font_size, 0 )
|
||||
|
||||
if active {
|
||||
ui_parent(value_txt)
|
||||
|
@ -27,7 +27,7 @@ UI_Window_ChildLayout :: enum(i32) {
|
||||
|
||||
@(deferred_in=ui_window_end_auto)
|
||||
ui_window :: proc (window : ^UI_Window, label : string,
|
||||
title : StrRunesPair = {},
|
||||
title : StrCached = {},
|
||||
closable := true,
|
||||
maximizable := true,
|
||||
draggable := true,
|
||||
@ -41,7 +41,7 @@ ui_window :: proc (window : ^UI_Window, label : string,
|
||||
}
|
||||
|
||||
ui_window_begin :: proc( window : ^UI_Window, label : string,
|
||||
title : StrRunesPair = {},
|
||||
title : StrCached = {},
|
||||
closable := true,
|
||||
maximizable := true,
|
||||
draggable := true,
|
||||
@ -83,7 +83,7 @@ ui_window_begin :: proc( window : ^UI_Window, label : string,
|
||||
scope(theme_transparent)
|
||||
vb = ui_vbox(.Top_To_Bottom, str_fmt_tmp("%s.vb", label))
|
||||
|
||||
if len(title.str) > 0 || closable || maximizable || draggable {
|
||||
if len(title) > 0 || closable || maximizable || draggable {
|
||||
dragged, maximized, closed = ui_window_bar(window, title, closable, maximizable, draggable)
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ ui_window_end :: proc (window : ^UI_Window)
|
||||
}
|
||||
|
||||
ui_window_end_auto :: proc( window : ^UI_Window, label : string,
|
||||
title : StrRunesPair = {},
|
||||
title : StrCached = {},
|
||||
closable := true,
|
||||
maximizable := true,
|
||||
draggable := true,
|
||||
@ -121,7 +121,7 @@ ui_window_end_auto :: proc( window : ^UI_Window, label : string,
|
||||
}
|
||||
|
||||
ui_window_bar :: proc( window : ^UI_Window,
|
||||
title : StrRunesPair = {},
|
||||
title : StrCached = {},
|
||||
closable := true,
|
||||
maximizable := true,
|
||||
draggable := true,
|
||||
@ -132,13 +132,13 @@ ui_window_bar :: proc( window : ^UI_Window,
|
||||
draggable_flag : UI_BoxFlags = draggable ? {.Mouse_Clickable} : {}
|
||||
|
||||
scope(theme_window_bar)
|
||||
bar = ui_hbox(.Left_To_Right, str_fmt_tmp("%s.bar", frame.label.str), draggable_flag);
|
||||
bar = ui_hbox(.Left_To_Right, str_fmt_tmp("%s.bar", frame.label), draggable_flag);
|
||||
ui_parent(bar)
|
||||
|
||||
if len(title.str) > 0
|
||||
if len(title) > 0
|
||||
{
|
||||
scope(theme_text)
|
||||
tile_text = ui_text( str_fmt_tmp("%s.title_text", bar.label.str), title, {.Disabled}); {
|
||||
tile_text = ui_text( str_fmt_tmp("%s.title_text", bar.label), title, {.Disabled}); {
|
||||
using tile_text
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins = { 0, 0, 15, 0}
|
||||
@ -149,7 +149,7 @@ ui_window_bar :: proc( window : ^UI_Window,
|
||||
scope(theme_window_bar_btn)
|
||||
if maximizable
|
||||
{
|
||||
maximize_btn = ui_button( str_fmt_tmp("%v.maximize_btn", bar.label.str) ); {
|
||||
maximize_btn = ui_button( str_fmt_tmp("%v.maximize_btn", bar.label) ); {
|
||||
using maximize_btn
|
||||
if maximize_btn.pressed {
|
||||
is_maximized = ~is_maximized
|
||||
|
Loading…
x
Reference in New Issue
Block a user