Remove rune tracking for string cache, + vecache changes

Getting ready to de-hardcode vefontcache shaders
This commit is contained in:
Edward R. Gonzalez 2025-01-06 14:12:55 -05:00
parent f1f98ffafb
commit 0350a0c282
26 changed files with 284 additions and 174 deletions

View File

@ -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

View File

@ -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,
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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))
}

View File

@ -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 )

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -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" )

View File

@ -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

View File

@ -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 {

View File

@ -15,8 +15,8 @@ ProjectConfig :: struct {
}
Project :: struct {
path : StrRunesPair,
name : StrRunesPair,
path : StrCached,
name : StrCached,
config : ProjectConfig,
codebase : CodeBase,

View File

@ -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 )

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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 )

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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