From 07c41a75fc82b6c612bf5d539ebd7065d34cff78 Mon Sep 17 00:00:00 2001 From: Katajisto Date: Sun, 29 Mar 2026 17:59:49 +0300 Subject: [PATCH] palette picker --- log_nvprosample.txt | 137 +---------------------------------- src/assets/asset_manager.jai | 6 ++ src/assets/loaders.jai | 34 +++++++++ src/editor/trile_editor.jai | 122 ++++++++++++++++++++++++++----- src/trile.jai | 17 +++++ 5 files changed, 163 insertions(+), 153 deletions(-) diff --git a/log_nvprosample.txt b/log_nvprosample.txt index 67cd1d4..f10d512 100644 --- a/log_nvprosample.txt +++ b/log_nvprosample.txt @@ -24,139 +24,4 @@ VK_KHR_deferred_host_operations VK_KHR_acceleration_structure VK_KHR_ray_query -BLAS Compaction: 2.4MB -> 0.8MB (1.6MB saved, 66.1% smaller) -_______________ -Vulkan Version: - - available: 1.4.309 - - requesting: 1.3.0 -______________________ -Used Instance Layers : -VK_LAYER_KHRONOS_validation - -Used Instance Extensions : -____________________ -Devices : 1 -0: AMD Radeon RX 6950 XT - - Compatible -Compatible physical devices found : 1 -Using Device: - - Device Name : AMD Radeon RX 6950 XT - - Vendor : AMD - - Driver Version : 2.0.341 - - API Version : 1.4.308 - - Device Type : Discrete GPU -________________________ -Used Device Extensions : -VK_KHR_deferred_host_operations -VK_KHR_acceleration_structure -VK_KHR_ray_query - -BLAS Compaction: 2.4MB -> 0.8MB (1.6MB saved, 66.1% smaller) -_______________ -Vulkan Version: - - available: 1.4.309 - - requesting: 1.3.0 -______________________ -Used Instance Layers : -VK_LAYER_KHRONOS_validation - -Used Instance Extensions : -____________________ -Devices : 1 -0: AMD Radeon RX 6950 XT - - Compatible -Compatible physical devices found : 1 -Using Device: - - Device Name : AMD Radeon RX 6950 XT - - Vendor : AMD - - Driver Version : 2.0.341 - - API Version : 1.4.308 - - Device Type : Discrete GPU -________________________ -Used Device Extensions : -VK_KHR_deferred_host_operations -VK_KHR_acceleration_structure -VK_KHR_ray_query - -BLAS Compaction: 2.4MB -> 0.8MB (1.6MB saved, 66.1% smaller) -_______________ -Vulkan Version: - - available: 1.4.309 - - requesting: 1.3.0 -______________________ -Used Instance Layers : -VK_LAYER_KHRONOS_validation - -Used Instance Extensions : -____________________ -Devices : 1 -0: AMD Radeon RX 6950 XT - - Compatible -Compatible physical devices found : 1 -Using Device: - - Device Name : AMD Radeon RX 6950 XT - - Vendor : AMD - - Driver Version : 2.0.341 - - API Version : 1.4.308 - - Device Type : Discrete GPU -________________________ -Used Device Extensions : -VK_KHR_deferred_host_operations -VK_KHR_acceleration_structure -VK_KHR_ray_query - -BLAS Compaction: 2.4MB -> 0.8MB (1.6MB saved, 66.1% smaller) -_______________ -Vulkan Version: - - available: 1.4.309 - - requesting: 1.3.0 -______________________ -Used Instance Layers : -VK_LAYER_KHRONOS_validation - -Used Instance Extensions : -____________________ -Devices : 1 -0: AMD Radeon RX 6950 XT - - Compatible -Compatible physical devices found : 1 -Using Device: - - Device Name : AMD Radeon RX 6950 XT - - Vendor : AMD - - Driver Version : 2.0.341 - - API Version : 1.4.308 - - Device Type : Discrete GPU -________________________ -Used Device Extensions : -VK_KHR_deferred_host_operations -VK_KHR_acceleration_structure -VK_KHR_ray_query - -BLAS Compaction: 2.4MB -> 0.8MB (1.6MB saved, 66.1% smaller) -_______________ -Vulkan Version: - - available: 1.4.309 - - requesting: 1.3.0 -______________________ -Used Instance Layers : -VK_LAYER_KHRONOS_validation - -Used Instance Extensions : -____________________ -Devices : 1 -0: AMD Radeon RX 6950 XT - - Compatible -Compatible physical devices found : 1 -Using Device: - - Device Name : AMD Radeon RX 6950 XT - - Vendor : AMD - - Driver Version : 2.0.341 - - API Version : 1.4.308 - - Device Type : Discrete GPU -________________________ -Used Device Extensions : -VK_KHR_deferred_host_operations -VK_KHR_acceleration_structure -VK_KHR_ray_query - -BLAS Compaction: 2.4MB -> 0.8MB (1.6MB saved, 66.1% smaller) +BLAS Compaction: 2.6MB -> 0.9MB (1.7MB saved, 66.1% smaller) diff --git a/src/assets/asset_manager.jai b/src/assets/asset_manager.jai index dee6c20..19bb55a 100644 --- a/src/assets/asset_manager.jai +++ b/src/assets/asset_manager.jai @@ -328,6 +328,12 @@ add_resources_from_pack :: (pack: *Loaded_Pack) { log_info("Loaded % particle definitions from pack", g_emitter_defs.count); } } + case "hex"; + pal : Loaded_Palette; + pal.name = sprint("%", name); + pal.entries = load_hex_palette_from_memory(v.data); + array_add(*g_palettes, pal); + log_info("Loaded % colors from hex palette(%)", pal.entries.count, v.name); case "ttf"; // Load into a font. Add to free list. case; diff --git a/src/assets/loaders.jai b/src/assets/loaders.jai index 1aa940f..04c03f1 100644 --- a/src/assets/loaders.jai +++ b/src/assets/loaders.jai @@ -30,6 +30,40 @@ create_string_from_memory :: (data: []u8) -> string { return s; } +load_hex_palette_from_memory :: (data: []u8) -> [..]Palette_Entry { + entries : [..]Palette_Entry; + parse_hex_byte :: (s: string) -> (u8, bool) { + val : u8 = 0; + for i: 0..1 { + c := s[i]; + digit : u8; + if c >= #char "0" && c <= #char "9" digit = c - #char "0"; + else if c >= #char "a" && c <= #char "f" digit = c - #char "a" + 10; + else if c >= #char "A" && c <= #char "F" digit = c - #char "A" + 10; + else return 0, false; + val = val * 16 + digit; + } + return val, true; + } + + s := create_string_from_memory(data); + for line: split(s, "\n") { + trimmed := trim(line); + if trimmed.count != 6 then continue; + rb, ok1 := parse_hex_byte(slice(trimmed, 0, 2)); + gb, ok2 := parse_hex_byte(slice(trimmed, 2, 2)); + bb, ok3 := parse_hex_byte(slice(trimmed, 4, 2)); + if !ok1 || !ok2 || !ok3 then continue; + entry : Palette_Entry; + entry.name = sprint("#%", trimmed); + entry.r = cast(float)rb / 255.0; + entry.g = cast(float)gb / 255.0; + entry.b = cast(float)bb / 255.0; + array_add(*entries, entry); + } + return entries; +} + load_wav_from_memory :: (data: []u8) -> Audio_Data { Wav :: #import "Wav_File"; audio : Audio_Data; diff --git a/src/editor/trile_editor.jai b/src/editor/trile_editor.jai index cb6a2c3..fec0178 100644 --- a/src/editor/trile_editor.jai +++ b/src/editor/trile_editor.jai @@ -250,6 +250,8 @@ get_trile_editor_camera :: () -> Camera { global_palette_scroll : float = 0.0; trile_palette_scroll : float = 0.0; +use_color_picker : bool = false; +selected_palette : s32 = 0; draw_tool_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) { r := area; @@ -275,23 +277,110 @@ draw_tool_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) { }; } +draw_swatches :: (entries: []Palette_Entry, inside: GR.Rect, block: float, scroll: *float, id_offset: s32, theme: *GR.Overall_Theme) -> (end_y: float) { + cols := max(1, cast(int)(inside.w / block)); + for entry, idx: entries { + er : GR.Rect; + er.x = inside.x + (idx % cols) * block; + er.y = inside.y - scroll.* + (idx / cols) * block; + er.w = block; er.h = block; + btn := theme.button_theme; + btn.surface_color = .{entry.r, entry.g, entry.b, 1.0}; + if GR.button(er, "", *btn, id_offset + cast(s32)idx) { + current_color = .{entry.r, entry.g, entry.b}; + roughness = xx entry.roughness; + metallic = xx entry.metallic; + emittance = xx entry.emittance; + } + } + rows := ifx entries.count > 0 then (entries.count + cols - 1) / cols else 0; + return inside.y + rows * block; +} + draw_material_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) { - r := area; - r.h = ui_h(42, 0); - GR.color_picker(r, *current_color, *theme.color_picker_theme); - r.y += r.h; - r.h = ui_h(100,0) - r.y; - r.h -= ui_h(18,0); - r.h /= 2; - region, inside := GR.begin_scrollable_region(r, *theme.scrollable_region_theme); - s := inside; - GR.end_scrollable_region(region, s.x + s.w, s.y + s.h, *global_palette_scroll); - r.y += r.h; - region, inside = GR.begin_scrollable_region(r, *theme.scrollable_region_theme); - s = inside; - GR.end_scrollable_region(region, s.x + s.w, s.y + s.h, *trile_palette_scroll); - r.y += r.h; - r.h = ui_h(3,2); + r := area; + row_h := ui_h(4, 0); + block := ui_h(3, 2); + bottom := area.y + area.h; + sliders_h := ui_h(18, 0); + + // Toggle: Palette | Color Picker + r.h = row_h; + half := r.w / 2; + r.w = half; + if GR.button(r, "Palette", *t_button_selectable(theme, !use_color_picker)) then use_color_picker = false; + r.x += half; + if GR.button(r, "Color Picker", *t_button_selectable(theme, use_color_picker)) then use_color_picker = true; + r.x = area.x; r.w = area.w; + r.y += row_h; + + available := bottom - r.y - sliders_h; + top_h := ifx use_color_picker then ui_h(42, 0) else available / 2; + bot_h := available - top_h; + + r.h = top_h; + if use_color_picker { + GR.color_picker(r, *current_color, *theme.color_picker_theme); + } else { + // Palette file selector + if g_palettes.count > 1 { + r.h = row_h; + pal_w := r.w / cast(float)g_palettes.count; + for pal, idx: g_palettes { + pr := r; + pr.x = area.x + idx * pal_w; + pr.w = pal_w; + if GR.button(pr, pal.name, *t_button_selectable(theme, cast(s32)idx == selected_palette), cast(s32)idx + 20000) { + selected_palette = cast(s32)idx; + global_palette_scroll = 0; + } + } + r.y += row_h; + top_h -= row_h; + r.h = top_h; + } + entries : []Palette_Entry; + if g_palettes.count > 0 { + selected_palette = clamp(selected_palette, 0, cast(s32)g_palettes.count - 1); + entries = g_palettes[selected_palette].entries; + } + region, inside := GR.begin_scrollable_region(r, *theme.scrollable_region_theme); + end_y := draw_swatches(entries, inside, block, *global_palette_scroll, 0, theme); + GR.end_scrollable_region(region, inside.x + inside.w, end_y, *global_palette_scroll); + } + r.y += top_h; + + // Trile material picker + unique_mats : [..]Material; + unique_mats.allocator = temp; + for x: 0..15 for y: 0..15 for z: 0..15 { + trix := editor_current_trile.trixels[x][y][z]; + if trix.empty then continue; + mr, mg, mb, ma := material_to_rgba(trix.material); + key := (cast(u32)mr << 24) | (cast(u32)mg << 16) | (cast(u32)mb << 8) | cast(u32)ma; + already := false; + for um: unique_mats { + ur, ug, ub, ua := material_to_rgba(um); + if ((cast(u32)ur << 24) | (cast(u32)ug << 16) | (cast(u32)ub << 8) | cast(u32)ua) == key { already = true; break; } + } + if !already array_add(*unique_mats, trix.material); + } + as_entries : [..]Palette_Entry; + as_entries.allocator = temp; + for mat: unique_mats { + e : Palette_Entry; + e.r = mat.color.x; e.g = mat.color.y; e.b = mat.color.z; + e.roughness = mat.roughness; e.metallic = mat.metallic; e.emittance = mat.emittance; + array_add(*as_entries, e); + } + + r.h = bot_h; + region2, inside2 := GR.begin_scrollable_region(r, *theme.scrollable_region_theme); + end_y2 := draw_swatches(as_entries, inside2, block, *trile_palette_scroll, 10000, theme); + GR.end_scrollable_region(region2, inside2.x + inside2.w, end_y2, *trile_palette_scroll); + r.y += bot_h; + + r.h = ui_h(3, 2); GR.label(r, "Roughness", *t_label_left(theme)); r.y += r.h; GR.slider(r, *roughness, 0, 7, 1, *theme.slider_theme); @@ -303,7 +392,6 @@ draw_material_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) { GR.label(r, "Emittance", *t_label_left(theme)); r.y += r.h; GR.slider(r, *emittance, 0, 2, 1, *theme.slider_theme); - } diff --git a/src/trile.jai b/src/trile.jai index 492869f..88380d7 100644 --- a/src/trile.jai +++ b/src/trile.jai @@ -143,6 +143,23 @@ Material :: struct { color : Vector3 = .{1.0, 0.0, 1.0}; } +Palette_Entry :: struct { + name : string; + r : float = 1.0; + g : float = 0.0; + b : float = 1.0; + roughness : int = 4; + metallic : int = 0; + emittance : int = 0; +} + +Loaded_Palette :: struct { + name : string; + entries : [..]Palette_Entry; +} + +g_palettes : [..]Loaded_Palette; + Trixel :: struct { material : Material; empty : bool = false;