From 9ac8c44b04ca1837eb604d0f820943cf0861d410 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Wed, 22 Jul 2026 13:08:25 -0700 Subject: [PATCH] simplify color picker script --- client/script/color_picker.lua | 92 ++++++++++++++++------------------ 1 file changed, 42 insertions(+), 50 deletions(-) diff --git a/client/script/color_picker.lua b/client/script/color_picker.lua index 2573134..2e6a286 100644 --- a/client/script/color_picker.lua +++ b/client/script/color_picker.lua @@ -15,23 +15,29 @@ local state = { rgb = {0, 0, 0, 1}, saved = {}, hex_string = "#000000FF", - hex_len = 8, } for i = 1, 12 do state.saved[i] = {0, 0, 0, 0} end +local function clamp01(x) return math.max(0, math.min(1, x)) end + local function update_hex_string() state.hex_string = string.format("#%02X%02X%02X%02X", math.floor(state.rgb[1]*255 + 0.5), math.floor(state.rgb[2]*255 + 0.5), math.floor(state.rgb[3]*255 + 0.5), math.floor(state.rgb[4]*255 + 0.5)) - state.hex_len = 8 ui.set_string(0, 0, state.hex_string) end +local function sync_rgb_from_hsv() + state.rgb[1], state.rgb[2], state.rgb[3] = + ui.hsv_to_rgb(state.hsv[1], state.hsv[2], state.hsv[3]) + update_hex_string() +end + local function sv_pick(s, v) - s = math.max(0, math.min(1, s)) - v = math.max(0, math.min(1, v)) + s = clamp01(s) + v = clamp01(v) state.hsv[2] = s state.hsv[3] = v @@ -41,16 +47,13 @@ local function sv_pick(s, v) end ui.set_pos(0, 3, s*130 - 3, 130 - v*130 - 3) - state.rgb[1], state.rgb[2], state.rgb[3] = - ui.hsv_to_rgb(state.hsv[1], state.hsv[2], state.hsv[3]) - update_hex_string() + sync_rgb_from_hsv() end local function hue_set(h) - h = math.max(0, math.min(1, h)) + h = clamp01(h) state.hsv[1] = h - -- sv square and sv select keep their per-corner s/v, only hue changes for _, drawable in ipairs({1, 4}) do for corner = 0, 3 do local _, s, v, a = ui.get_corner_color(0, drawable, corner) @@ -59,9 +62,7 @@ local function hue_set(h) end ui.set_pos(0, 6, 134, 2 + h*130) - state.rgb[1], state.rgb[2], state.rgb[3] = - ui.hsv_to_rgb(state.hsv[1], state.hsv[2], state.hsv[3]) - update_hex_string() + sync_rgb_from_hsv() end local function hex_string_highlight(value) @@ -80,20 +81,24 @@ local function set_saved(index, color) end end -function on_button(layer, element, x, y, button, action, mods) - if element == 1 then -- sv square - if action == PRESS and button == MOUSE_LEFT then - ui.focus(layer, element) - sv_pick(x, 1 - y) - elseif action == RELEASE and button == MOUSE_LEFT then - ui.blur() - end - return true +-- Sync HSV+visuals from state.rgb; used after setting state.rgb directly. +local function apply_state_rgb() + state.hsv[1], state.hsv[2], state.hsv[3] = + ui.rgb_to_hsv(state.rgb[1], state.rgb[2], state.rgb[3]) + hue_set(state.hsv[1]) + sv_pick(state.hsv[2], state.hsv[3]) +end - elseif element == 2 then -- hue bar +local drag = { + [1] = function(x, y) sv_pick(x, 1 - y) end, + [2] = function(x, y) hue_set(y) end, +} + +function on_button(layer, element, x, y, button, action, mods) + if drag[element] then if action == PRESS and button == MOUSE_LEFT then ui.focus(layer, element) - hue_set(y) + drag[element](x, y) elseif action == RELEASE and button == MOUSE_LEFT then ui.blur() end @@ -112,10 +117,7 @@ function on_button(layer, element, x, y, button, action, mods) if button == MOUSE_LEFT then local saved = state.saved[index] state.rgb = {saved[1], saved[2], saved[3], saved[4]} - state.hsv[1], state.hsv[2], state.hsv[3] = - ui.rgb_to_hsv(state.rgb[1], state.rgb[2], state.rgb[3]) - hue_set(state.hsv[1]) - sv_pick(state.hsv[2], state.hsv[3]) + apply_state_rgb() elseif button == MOUSE_RIGHT then set_saved(index, state.rgb) elseif button == MOUSE_MIDDLE then @@ -129,12 +131,11 @@ function on_button(layer, element, x, y, button, action, mods) end function on_cursor(layer, element, x, y) - if ui.is_focused(0, 1) then -- dragging the sv square - sv_pick(x, 1 - y) - return true - elseif ui.is_focused(0, 2) then -- dragging the hue bar - hue_set(y) - return true + for el, fn in pairs(drag) do + if ui.is_focused(0, el) then + fn(x, y) + return true + end end return false end @@ -152,31 +153,23 @@ function on_key(layer, element, key, action, mods) if action == PRESS then if key == KEY_ESCAPE then - state.rgb[1], state.rgb[2], state.rgb[3] = - ui.hsv_to_rgb(state.hsv[1], state.hsv[2], state.hsv[3]) - update_hex_string() + sync_rgb_from_hsv() ui.blur() elseif key == KEY_ENTER then local s = state.hex_string - state.rgb[1] = (tonumber(s:sub(2, 3), 16) or 0) / 255 - state.rgb[2] = (tonumber(s:sub(4, 5), 16) or 0) / 255 - state.rgb[3] = (tonumber(s:sub(6, 7), 16) or 0) / 255 - state.rgb[4] = (tonumber(s:sub(8, 9), 16) or 0) / 255 - state.hsv[1], state.hsv[2], state.hsv[3] = - ui.rgb_to_hsv(state.rgb[1], state.rgb[2], state.rgb[3]) - hue_set(state.hsv[1]) - sv_pick(state.hsv[2], state.hsv[3]) + for i = 1, 4 do + state.rgb[i] = (tonumber(s:sub(2*i, 2*i + 1), 16) or 0) / 255 + end + apply_state_rgb() ui.blur() elseif key == KEY_BACKSPACE then - if state.hex_len > 0 then - state.hex_string = state.hex_string:sub(1, state.hex_len) - state.hex_len = state.hex_len - 1 + if #state.hex_string > 1 then + state.hex_string = state.hex_string:sub(1, -2) ui.set_string(0, 0, state.hex_string) end end end - -- consume all keys while the hex input is focused return true end @@ -185,9 +178,8 @@ function on_text(layer, element, codepoint) if codepoint < 128 then local ch = string.char(codepoint):upper() - if ch:match("[0-9A-F]") and state.hex_len < 8 then + if ch:match("[0-9A-F]") and #state.hex_string < 9 then state.hex_string = state.hex_string .. ch - state.hex_len = state.hex_len + 1 ui.set_string(0, 0, state.hex_string) end end