|
|
|
@ -15,23 +15,29 @@ local state = {
|
|
|
|
rgb = {0, 0, 0, 1},
|
|
|
|
rgb = {0, 0, 0, 1},
|
|
|
|
saved = {},
|
|
|
|
saved = {},
|
|
|
|
hex_string = "#000000FF",
|
|
|
|
hex_string = "#000000FF",
|
|
|
|
hex_len = 8,
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for i = 1, 12 do state.saved[i] = {0, 0, 0, 0} end
|
|
|
|
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()
|
|
|
|
local function update_hex_string()
|
|
|
|
state.hex_string = string.format("#%02X%02X%02X%02X",
|
|
|
|
state.hex_string = string.format("#%02X%02X%02X%02X",
|
|
|
|
math.floor(state.rgb[1]*255 + 0.5),
|
|
|
|
math.floor(state.rgb[1]*255 + 0.5),
|
|
|
|
math.floor(state.rgb[2]*255 + 0.5),
|
|
|
|
math.floor(state.rgb[2]*255 + 0.5),
|
|
|
|
math.floor(state.rgb[3]*255 + 0.5),
|
|
|
|
math.floor(state.rgb[3]*255 + 0.5),
|
|
|
|
math.floor(state.rgb[4]*255 + 0.5))
|
|
|
|
math.floor(state.rgb[4]*255 + 0.5))
|
|
|
|
state.hex_len = 8
|
|
|
|
|
|
|
|
ui.set_string(0, 0, state.hex_string)
|
|
|
|
ui.set_string(0, 0, state.hex_string)
|
|
|
|
end
|
|
|
|
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)
|
|
|
|
local function sv_pick(s, v)
|
|
|
|
s = math.max(0, math.min(1, s))
|
|
|
|
s = clamp01(s)
|
|
|
|
v = math.max(0, math.min(1, v))
|
|
|
|
v = clamp01(v)
|
|
|
|
state.hsv[2] = s
|
|
|
|
state.hsv[2] = s
|
|
|
|
state.hsv[3] = v
|
|
|
|
state.hsv[3] = v
|
|
|
|
|
|
|
|
|
|
|
|
@ -41,16 +47,13 @@ local function sv_pick(s, v)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
ui.set_pos(0, 3, s*130 - 3, 130 - v*130 - 3)
|
|
|
|
ui.set_pos(0, 3, s*130 - 3, 130 - v*130 - 3)
|
|
|
|
|
|
|
|
|
|
|
|
state.rgb[1], state.rgb[2], state.rgb[3] =
|
|
|
|
sync_rgb_from_hsv()
|
|
|
|
ui.hsv_to_rgb(state.hsv[1], state.hsv[2], state.hsv[3])
|
|
|
|
|
|
|
|
update_hex_string()
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
local function hue_set(h)
|
|
|
|
local function hue_set(h)
|
|
|
|
h = math.max(0, math.min(1, h))
|
|
|
|
h = clamp01(h)
|
|
|
|
state.hsv[1] = 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 _, drawable in ipairs({1, 4}) do
|
|
|
|
for corner = 0, 3 do
|
|
|
|
for corner = 0, 3 do
|
|
|
|
local _, s, v, a = ui.get_corner_color(0, drawable, corner)
|
|
|
|
local _, s, v, a = ui.get_corner_color(0, drawable, corner)
|
|
|
|
@ -59,9 +62,7 @@ local function hue_set(h)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
ui.set_pos(0, 6, 134, 2 + h*130)
|
|
|
|
ui.set_pos(0, 6, 134, 2 + h*130)
|
|
|
|
|
|
|
|
|
|
|
|
state.rgb[1], state.rgb[2], state.rgb[3] =
|
|
|
|
sync_rgb_from_hsv()
|
|
|
|
ui.hsv_to_rgb(state.hsv[1], state.hsv[2], state.hsv[3])
|
|
|
|
|
|
|
|
update_hex_string()
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
local function hex_string_highlight(value)
|
|
|
|
local function hex_string_highlight(value)
|
|
|
|
@ -80,20 +81,24 @@ local function set_saved(index, color)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function on_button(layer, element, x, y, button, action, mods)
|
|
|
|
-- Sync HSV+visuals from state.rgb; used after setting state.rgb directly.
|
|
|
|
if element == 1 then -- sv square
|
|
|
|
local function apply_state_rgb()
|
|
|
|
if action == PRESS and button == MOUSE_LEFT then
|
|
|
|
state.hsv[1], state.hsv[2], state.hsv[3] =
|
|
|
|
ui.focus(layer, element)
|
|
|
|
ui.rgb_to_hsv(state.rgb[1], state.rgb[2], state.rgb[3])
|
|
|
|
sv_pick(x, 1 - y)
|
|
|
|
hue_set(state.hsv[1])
|
|
|
|
elseif action == RELEASE and button == MOUSE_LEFT then
|
|
|
|
sv_pick(state.hsv[2], state.hsv[3])
|
|
|
|
ui.blur()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
if action == PRESS and button == MOUSE_LEFT then
|
|
|
|
ui.focus(layer, element)
|
|
|
|
ui.focus(layer, element)
|
|
|
|
hue_set(y)
|
|
|
|
drag[element](x, y)
|
|
|
|
elseif action == RELEASE and button == MOUSE_LEFT then
|
|
|
|
elseif action == RELEASE and button == MOUSE_LEFT then
|
|
|
|
ui.blur()
|
|
|
|
ui.blur()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
@ -112,10 +117,7 @@ function on_button(layer, element, x, y, button, action, mods)
|
|
|
|
if button == MOUSE_LEFT then
|
|
|
|
if button == MOUSE_LEFT then
|
|
|
|
local saved = state.saved[index]
|
|
|
|
local saved = state.saved[index]
|
|
|
|
state.rgb = {saved[1], saved[2], saved[3], saved[4]}
|
|
|
|
state.rgb = {saved[1], saved[2], saved[3], saved[4]}
|
|
|
|
state.hsv[1], state.hsv[2], state.hsv[3] =
|
|
|
|
apply_state_rgb()
|
|
|
|
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])
|
|
|
|
|
|
|
|
elseif button == MOUSE_RIGHT then
|
|
|
|
elseif button == MOUSE_RIGHT then
|
|
|
|
set_saved(index, state.rgb)
|
|
|
|
set_saved(index, state.rgb)
|
|
|
|
elseif button == MOUSE_MIDDLE then
|
|
|
|
elseif button == MOUSE_MIDDLE then
|
|
|
|
@ -129,12 +131,11 @@ function on_button(layer, element, x, y, button, action, mods)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function on_cursor(layer, element, x, y)
|
|
|
|
function on_cursor(layer, element, x, y)
|
|
|
|
if ui.is_focused(0, 1) then -- dragging the sv square
|
|
|
|
for el, fn in pairs(drag) do
|
|
|
|
sv_pick(x, 1 - y)
|
|
|
|
if ui.is_focused(0, el) then
|
|
|
|
return true
|
|
|
|
fn(x, y)
|
|
|
|
elseif ui.is_focused(0, 2) then -- dragging the hue bar
|
|
|
|
return true
|
|
|
|
hue_set(y)
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
@ -152,31 +153,23 @@ function on_key(layer, element, key, action, mods)
|
|
|
|
|
|
|
|
|
|
|
|
if action == PRESS then
|
|
|
|
if action == PRESS then
|
|
|
|
if key == KEY_ESCAPE then
|
|
|
|
if key == KEY_ESCAPE then
|
|
|
|
state.rgb[1], state.rgb[2], state.rgb[3] =
|
|
|
|
sync_rgb_from_hsv()
|
|
|
|
ui.hsv_to_rgb(state.hsv[1], state.hsv[2], state.hsv[3])
|
|
|
|
|
|
|
|
update_hex_string()
|
|
|
|
|
|
|
|
ui.blur()
|
|
|
|
ui.blur()
|
|
|
|
elseif key == KEY_ENTER then
|
|
|
|
elseif key == KEY_ENTER then
|
|
|
|
local s = state.hex_string
|
|
|
|
local s = state.hex_string
|
|
|
|
state.rgb[1] = (tonumber(s:sub(2, 3), 16) or 0) / 255
|
|
|
|
for i = 1, 4 do
|
|
|
|
state.rgb[2] = (tonumber(s:sub(4, 5), 16) or 0) / 255
|
|
|
|
state.rgb[i] = (tonumber(s:sub(2*i, 2*i + 1), 16) or 0) / 255
|
|
|
|
state.rgb[3] = (tonumber(s:sub(6, 7), 16) or 0) / 255
|
|
|
|
end
|
|
|
|
state.rgb[4] = (tonumber(s:sub(8, 9), 16) or 0) / 255
|
|
|
|
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])
|
|
|
|
|
|
|
|
ui.blur()
|
|
|
|
ui.blur()
|
|
|
|
elseif key == KEY_BACKSPACE then
|
|
|
|
elseif key == KEY_BACKSPACE then
|
|
|
|
if state.hex_len > 0 then
|
|
|
|
if #state.hex_string > 1 then
|
|
|
|
state.hex_string = state.hex_string:sub(1, state.hex_len)
|
|
|
|
state.hex_string = state.hex_string:sub(1, -2)
|
|
|
|
state.hex_len = state.hex_len - 1
|
|
|
|
|
|
|
|
ui.set_string(0, 0, state.hex_string)
|
|
|
|
ui.set_string(0, 0, state.hex_string)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-- consume all keys while the hex input is focused
|
|
|
|
|
|
|
|
return true
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
@ -185,9 +178,8 @@ function on_text(layer, element, codepoint)
|
|
|
|
|
|
|
|
|
|
|
|
if codepoint < 128 then
|
|
|
|
if codepoint < 128 then
|
|
|
|
local ch = string.char(codepoint):upper()
|
|
|
|
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_string = state.hex_string .. ch
|
|
|
|
state.hex_len = state.hex_len + 1
|
|
|
|
|
|
|
|
ui.set_string(0, 0, state.hex_string)
|
|
|
|
ui.set_string(0, 0, state.hex_string)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|