mirror of
https://github.com/Mjokfox/color_picker.git
synced 2024-12-04 16:04:02 -05:00
Compare commits
3 commits
1c1f7ae464
...
eea1cbd569
Author | SHA1 | Date | |
---|---|---|---|
|
eea1cbd569 | ||
|
453b7896ff | ||
|
fb9a4fa923 |
3 changed files with 213 additions and 176 deletions
110
converters.lua
Normal file
110
converters.lua
Normal file
|
@ -0,0 +1,110 @@
|
|||
local max_value = 15
|
||||
-- magic hsv/rgb functions
|
||||
function hue_to_rgb(p, q, t)
|
||||
if t < 0 then t = t + 1 end
|
||||
if t > 1 then t = t - 1 end
|
||||
if t < 1/6 then return p + (q - p) * 6 * t end
|
||||
if t < 1/2 then return q end
|
||||
if t < 2/3 then return p + (q - p) * (2/3 - t) * 6 end
|
||||
return p
|
||||
end
|
||||
|
||||
-- magic hsv/rgb functions
|
||||
function hsl_to_rgb(h, s, l)
|
||||
local r, g, b
|
||||
|
||||
if s == 0 then
|
||||
r = l
|
||||
g = l
|
||||
b = l
|
||||
else
|
||||
local q = l < 0.5 and l * (1 + s) or l + s - l * s
|
||||
local p = 2 * l - q
|
||||
r = hue_to_rgb(p, q, h + 1/3)
|
||||
g = hue_to_rgb(p, q, h)
|
||||
b = hue_to_rgb(p, q, h - 1/3)
|
||||
end
|
||||
|
||||
return math.floor(r * max_value), math.floor(g * max_value), math.floor(b * max_value)
|
||||
end
|
||||
|
||||
-- magic hsv/rgb functions
|
||||
function hsv_to_rgb(h, s, v)
|
||||
local r, g, b
|
||||
|
||||
local i = math.floor(h * 6)
|
||||
local f = h * 6 - i
|
||||
local p = v * (1 - s)
|
||||
local q = v * (1 - f * s)
|
||||
local t = v * (1 - (1 - f) * s)
|
||||
|
||||
i = i % 6
|
||||
|
||||
if i == 0 then
|
||||
r, g, b = v, t, p
|
||||
elseif i == 1 then
|
||||
r, g, b = q, v, p
|
||||
elseif i == 2 then
|
||||
r, g, b = p, v, t
|
||||
elseif i == 3 then
|
||||
r, g, b = p, q, v
|
||||
elseif i == 4 then
|
||||
r, g, b = t, p, v
|
||||
elseif i == 5 then
|
||||
r, g, b = v, p, q
|
||||
end
|
||||
|
||||
return math.floor(r * max_value), math.floor(g * max_value), math.floor(b * max_value)
|
||||
end
|
||||
|
||||
-- magic oklab stuff
|
||||
function lch_to_lab(L, C, h)
|
||||
local a = C * math.cos(h * math.pi / 180)
|
||||
local b = C * math.sin(h * math.pi / 180)
|
||||
return L, a, b
|
||||
end
|
||||
|
||||
-- magic oklab stuff
|
||||
function oklab_to_linear_srgb(L, a, b)
|
||||
local l_ = (L + 0.3963377774 * a + 0.2158037573 * b) ^ 3
|
||||
local m_ = (L - 0.1055613458 * a - 0.0638541728 * b) ^ 3
|
||||
local s_ = (L - 0.0894841775 * a - 1.2914855480 * b) ^ 3
|
||||
|
||||
local r = 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_
|
||||
local g = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_
|
||||
local b = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.7076147010 * s_
|
||||
|
||||
return r, g, b
|
||||
end
|
||||
|
||||
-- magic oklab stuff
|
||||
function linear_to_srgb(x)
|
||||
if x <= 0.0031308 then
|
||||
return 12.92 * x
|
||||
else
|
||||
return 1.055 * x^(1/2.4) - 0.055
|
||||
end
|
||||
end
|
||||
|
||||
-- magic oklab stuff
|
||||
function lch_to_rgb(L, C, h)
|
||||
local r, g, b = oklab_to_linear_srgb(lch_to_lab(L, C, h))
|
||||
|
||||
r = linear_to_srgb(r)
|
||||
g = linear_to_srgb(g)
|
||||
b = linear_to_srgb(b)
|
||||
|
||||
return math.floor(r * max_value), math.floor(g * max_value), math.floor(b * max_value)
|
||||
end
|
||||
|
||||
-- helper function
|
||||
function toHex(decimal)
|
||||
if (decimal < 0) then
|
||||
decimal = 0
|
||||
end
|
||||
if (decimal > max_value) then
|
||||
decimal = max_value
|
||||
end
|
||||
local hex = string.format("%01x", decimal)
|
||||
return hex
|
||||
end
|
277
init.lua
277
init.lua
|
@ -1,123 +1,31 @@
|
|||
local color_picker = {}
|
||||
local width = 64
|
||||
local height = 64;
|
||||
local max_value = 15
|
||||
local saturation = 0;
|
||||
local mapping_type_index = "2"
|
||||
local dropdown_index = "3"
|
||||
local bars = {"0","100","50"}
|
||||
local fs = {}
|
||||
|
||||
-- magic hsv/rgb functions
|
||||
local function hue_to_rgb(p, q, t)
|
||||
if t < 0 then t = t + 1 end
|
||||
if t > 1 then t = t - 1 end
|
||||
if t < 1/6 then return p + (q - p) * 6 * t end
|
||||
if t < 1/2 then return q end
|
||||
if t < 2/3 then return p + (q - p) * (2/3 - t) * 6 end
|
||||
return p
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
dofile(modpath.."/converters.lua")
|
||||
|
||||
local width = minetest.settings:get("map_size")
|
||||
|
||||
if (width == nil) then
|
||||
width = 64
|
||||
minetest.settings:set("map_size",64)
|
||||
end
|
||||
|
||||
-- magic hsv/rgb functions
|
||||
local function hsl_to_rgb(h, s, l)
|
||||
local r, g, b
|
||||
|
||||
if s == 0 then
|
||||
r = l
|
||||
g = l
|
||||
b = l
|
||||
else
|
||||
local q = l < 0.5 and l * (1 + s) or l + s - l * s
|
||||
local p = 2 * l - q
|
||||
r = hue_to_rgb(p, q, h + 1/3)
|
||||
g = hue_to_rgb(p, q, h)
|
||||
b = hue_to_rgb(p, q, h - 1/3)
|
||||
end
|
||||
|
||||
return math.floor(r * max_value), math.floor(g * max_value), math.floor(b * max_value)
|
||||
end
|
||||
|
||||
-- magic hsv/rgb functions
|
||||
local function hsv_to_rgb(h, s, v)
|
||||
local r, g, b
|
||||
|
||||
local i = math.floor(h * 6)
|
||||
local f = h * 6 - i
|
||||
local p = v * (1 - s)
|
||||
local q = v * (1 - f * s)
|
||||
local t = v * (1 - (1 - f) * s)
|
||||
|
||||
i = i % 6
|
||||
|
||||
if i == 0 then
|
||||
r, g, b = v, t, p
|
||||
elseif i == 1 then
|
||||
r, g, b = q, v, p
|
||||
elseif i == 2 then
|
||||
r, g, b = p, v, t
|
||||
elseif i == 3 then
|
||||
r, g, b = p, q, v
|
||||
elseif i == 4 then
|
||||
r, g, b = t, p, v
|
||||
elseif i == 5 then
|
||||
r, g, b = v, p, q
|
||||
end
|
||||
|
||||
return math.floor(r * max_value), math.floor(g * max_value), math.floor(b * max_value)
|
||||
end
|
||||
|
||||
-- magic oklab stuff
|
||||
local function lch_to_lab(L, C, h)
|
||||
local a = C * math.cos(h * math.pi / 180)
|
||||
local b = C * math.sin(h * math.pi / 180)
|
||||
return L, a, b
|
||||
end
|
||||
|
||||
-- magic oklab stuff
|
||||
local function oklab_to_linear_srgb(L, a, b)
|
||||
local l_ = (L + 0.3963377774 * a + 0.2158037573 * b) ^ 3
|
||||
local m_ = (L - 0.1055613458 * a - 0.0638541728 * b) ^ 3
|
||||
local s_ = (L - 0.0894841775 * a - 1.2914855480 * b) ^ 3
|
||||
|
||||
local r = 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_
|
||||
local g = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_
|
||||
local b = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.7076147010 * s_
|
||||
|
||||
return r, g, b
|
||||
end
|
||||
|
||||
-- magic oklab stuff
|
||||
local function linear_to_srgb(x)
|
||||
if x <= 0.0031308 then
|
||||
return 12.92 * x
|
||||
else
|
||||
return 1.055 * x^(1/2.4) - 0.055
|
||||
end
|
||||
end
|
||||
|
||||
-- magic oklab stuff
|
||||
local function lch_to_rgb(L, C, h)
|
||||
local r, g, b = oklab_to_linear_srgb(lch_to_lab(L, C, h))
|
||||
|
||||
r = linear_to_srgb(r)
|
||||
g = linear_to_srgb(g)
|
||||
b = linear_to_srgb(b)
|
||||
|
||||
return math.floor(r * max_value), math.floor(g * max_value), math.floor(b * max_value)
|
||||
end
|
||||
local height = width
|
||||
|
||||
-- helper function
|
||||
local function toHex(decimal)
|
||||
if (decimal < 0) then
|
||||
decimal = 0
|
||||
end
|
||||
if (decimal > max_value) then
|
||||
decimal = max_value
|
||||
end
|
||||
local hex = string.format("%01x", decimal)
|
||||
return hex
|
||||
local function TableConcat(t1,t2)
|
||||
for i=1,#t2 do
|
||||
t1[#t1+1] = t2[i]
|
||||
end
|
||||
return t1
|
||||
end
|
||||
|
||||
|
||||
-- color sliders
|
||||
local function assemble_sliders(x,y,w,h)
|
||||
-- labels
|
||||
|
@ -137,6 +45,7 @@ local function assemble_sliders(x,y,w,h)
|
|||
labels = {"L","C","h"}
|
||||
maxs = {100,100,360}
|
||||
units = {"%%","%%","\u{00B0}"}
|
||||
steps = {10,10,36}
|
||||
r,g,b = lch_to_rgb(bars[1]/100,bars[2]/100,bars[3])
|
||||
else
|
||||
labels = {"R","G","B"}
|
||||
|
@ -147,12 +56,16 @@ local function assemble_sliders(x,y,w,h)
|
|||
end end end
|
||||
local hexr,hexg,hexb = toHex(r),toHex(g),toHex(b)
|
||||
-- preview color
|
||||
buf[#buf + 1] = "label[".. x + w/3 ..",".. y + h/1.5 ..";click me!]"
|
||||
y=y+h
|
||||
buf[#buf + 1] = "item_image_button[".. x..",".. y ..";"..w..","..3*h..";hexcol:".. hexr .. hexg .. hexb ..";hexcol:".. hexr .. hexg .. hexb ..";]"
|
||||
local label = "click me!"
|
||||
local temp = minetest.formspec_escape(";")
|
||||
if (r==4 and g==2 and b==0) then label = "Nice"
|
||||
else if (r==6 and g==2 and b==1) then label = temp .."3"
|
||||
else if (r==6 and g==6 and b==6) then label = "Feeling devious today.."
|
||||
else if (r==7 and g==7 and b==7) then label = "Feeling lucky today.." end end end end
|
||||
buf[#buf + 1] = "item_image_button[".. x..",".. y+h ..";"..w..","..5*h..";hexcol:".. hexr .. hexg .. hexb ..";hexcol:".. hexr .. hexg .. hexb ..";"..label.."]"
|
||||
|
||||
-- generate the sliders
|
||||
y=y+2*h
|
||||
y=y+5*h
|
||||
for i=1,3 do
|
||||
buf[#buf + 1] = "label[".. x-0.4 ..",".. y+(i+0.5)*h ..";".. labels[i] .."]" -- label showing what kind of slider
|
||||
buf[#buf + 1] = "scrollbaroptions[min=0;max=".. maxs[i] ..";smallstep=".. steps[i] .."]" -- options
|
||||
|
@ -171,86 +84,95 @@ end
|
|||
-- color map
|
||||
local function Assemble_Map(x_off,y_off)
|
||||
local buf = {}
|
||||
buf[#buf + 1] = "label[".. x_off + 2 ..",".. y_off + 0.5 ..";click any color!]"
|
||||
local size = 12.8/(width + height)
|
||||
buf[#buf + 1] = "label[".. x_off + (width*size)/2 - string.len("click any color!")/15 ..",".. y_off + 0.5 ..";click any color!]"
|
||||
local label = "saturation"
|
||||
if (dropdown_index == "4") then label = "chroma" end
|
||||
if (dropdown_index ~= "1") then
|
||||
buf[#buf + 1] = "label[".. x_off + 6.6 ..",".. y_off + 0.5 ..";".. label .."]"
|
||||
y_off=y_off+1
|
||||
-- saturation slider
|
||||
buf[#buf + 1] = "scrollbaroptions[min=0;max=10;smallstep=1;largestep=3]"
|
||||
buf[#buf + 1] = "scrollbar[".. x_off + 7 ..",".. y_off ..";1,6.4;vertical;saturation;".. saturation .."]"
|
||||
else
|
||||
y_off=y_off+1
|
||||
end
|
||||
if (dropdown_index == "4") then label = "chroma " end
|
||||
if (dropdown_index == "1") then label = "red" end
|
||||
buf[#buf + 1] = "label[".. x_off + 7.5 - string.len(label)/15 ..",".. y_off + 0.5 ..";".. label .."]"
|
||||
y_off=y_off+1
|
||||
-- saturation slider
|
||||
local max = 10
|
||||
local step = 1;
|
||||
if (dropdown_index == "1") then max = 15; step = 1 end
|
||||
buf[#buf + 1] = "scrollbaroptions[min=0;max=".. max ..";smallstep=".. step ..";thumbsize=1]"
|
||||
buf[#buf + 1] = "scrollbar[".. x_off + 7 ..",".. y_off ..";0.5,6.4;vertical;saturation;".. saturation .."]"
|
||||
-- full map
|
||||
local size = 0.1
|
||||
|
||||
local size_increase = 1.5
|
||||
local y_axis,x_axis = "lightness","hue"
|
||||
local hexr,hexg,hexb
|
||||
local ohexr,ohexg,ohexb
|
||||
local temp_width = 1;
|
||||
local old_x = 0;
|
||||
local map_optimization = true;
|
||||
for y = 0,height-1 do
|
||||
for x = 0,width-1 do
|
||||
-- set r,g,b using the selected mapping method
|
||||
local r,g,b = 0,0,0;
|
||||
if (dropdown_index == "2") then
|
||||
y_axis,x_axis = "value","hue"
|
||||
r,g,b = hsv_to_rgb(x / width,1-saturation/10,(height-y) / height)
|
||||
else if (dropdown_index == "3") then
|
||||
r,g,b = hsl_to_rgb(x / width,1-saturation/10,(height-y) / height)
|
||||
else if (dropdown_index == "4") then
|
||||
y_axis = "p lightness"
|
||||
r,g,b = lch_to_rgb((height-y) / height, 1-saturation/10, 360*(x / width))
|
||||
else
|
||||
y_axis,x_axis = "",""
|
||||
r,g,b = math.floor(x/(width/4))+math.floor(y/(width/4))*(width/16),y%16,x%16
|
||||
end end end
|
||||
|
||||
hexr,hexg,hexb = toHex(r),toHex(g),toHex(b)
|
||||
if (x==0) then
|
||||
ohexr,ohexg,ohexb = hexr,hexg,hexb
|
||||
if (dropdown_index == "1") then
|
||||
local temp_size = 0.4
|
||||
local r,g,b
|
||||
for y = 0,15 do
|
||||
for x = 0,15 do
|
||||
r,g,b = 15-saturation,y%16,x%16
|
||||
hexr,hexg,hexb = toHex(r),toHex(g),toHex(b)
|
||||
buf[#buf + 1] = "item_image_button[".. x*temp_size + x_off ..",".. y*temp_size + y_off ..";"..(temp_size*size_increase)..","..(temp_size*size_increase)..";hexcol:".. hexr .. hexg .. hexb ..";hexcol:".. hexr .. hexg .. hexb ..";]"
|
||||
end
|
||||
|
||||
if (map_optimization) then
|
||||
if (ohexr == hexr and ohexg == hexg and ohexb == hexb) then
|
||||
temp_width = temp_width + 1
|
||||
if (temp_width == 2) then old_x = x end
|
||||
else
|
||||
-- use hexcol mod to display the buttons as their blocks
|
||||
if temp_width == 1 then
|
||||
old_x = x
|
||||
end
|
||||
buf[#buf + 1] = "item_image_button[".. old_x*size + x_off + 0.0001 ..",".. y*size + y_off + 0.0001 ..";"..size*temp_width..","..size..";hexcol:".. ohexr .. ohexg .. ohexb ..";hexcol:".. ohexr .. ohexg .. ohexb ..";]"
|
||||
temp_width = 1
|
||||
old_x = x;
|
||||
end
|
||||
ohexr,ohexg,ohexb = hexr,hexg,hexb
|
||||
else
|
||||
buf[#buf + 1] = "item_image_button[".. x*size + x_off + 0.0001 ..",".. y*size + y_off + 0.0001 ..";"..size..","..size..";hexcol:".. hexr .. hexg .. hexb ..";hexcol:".. hexr .. hexg .. hexb ..";]"
|
||||
end
|
||||
|
||||
end
|
||||
if (map_optimization) then
|
||||
if (temp_width>1) then
|
||||
buf[#buf + 1] = "item_image_button[".. old_x*size + x_off + 0.0001 ..",".. y*size + y_off + 0.0001 ..";"..size*(temp_width-1)..","..size..";hexcol:".. ohexr .. ohexg .. ohexb ..";hexcol:".. ohexr .. ohexg .. ohexb ..";]"
|
||||
temp_width = 1;
|
||||
y_axis,x_axis = "green","blue"
|
||||
else
|
||||
for y = 0,height-1 do
|
||||
for x = 0,width-1 do
|
||||
-- set r,g,b using the selected mapping method
|
||||
local r,g,b = 0,0,0;
|
||||
if (dropdown_index == "2") then
|
||||
y_axis,x_axis = "value","hue"
|
||||
r,g,b = hsv_to_rgb(x / width,1-saturation/10,(height-y) / height)
|
||||
else if (dropdown_index == "3") then
|
||||
r,g,b = hsl_to_rgb(x / width,1-saturation/10,(height-y) / height)
|
||||
else if (dropdown_index == "4") then
|
||||
y_axis = "p lightness"
|
||||
r,g,b = lch_to_rgb((height-y) / height, 1-saturation/10, 360*(x / width))
|
||||
else
|
||||
y_axis = "chroma"
|
||||
-- r,g,b = math.floor(x/(width/4))+math.floor(y/(width/4))*(width/16),y%16,x%16
|
||||
r,g,b = lch_to_rgb(1-saturation/10, (height-y) / height, 360*(x / width))
|
||||
end end end
|
||||
|
||||
hexr,hexg,hexb = toHex(r),toHex(g),toHex(b)
|
||||
if (x==0) then
|
||||
ohexr,ohexg,ohexb = hexr,hexg,hexb
|
||||
end
|
||||
|
||||
if (map_optimization) then
|
||||
if (ohexr == hexr and ohexg == hexg and ohexb == hexb) then
|
||||
temp_width = temp_width + 1
|
||||
if (temp_width == 2) then old_x = x end
|
||||
else
|
||||
-- use hexcol mod to display the buttons as their blocks
|
||||
if temp_width == 1 then
|
||||
old_x = x
|
||||
end
|
||||
buf[#buf + 1] = "item_image_button[".. old_x*size + x_off ..",".. y*size + y_off ..";"..size*(temp_width-1+size_increase)..","..(size*size_increase)..";hexcol:".. ohexr .. ohexg .. ohexb ..";hexcol:".. ohexr .. ohexg .. ohexb ..";]"
|
||||
temp_width = 1
|
||||
old_x = x;
|
||||
end
|
||||
ohexr,ohexg,ohexb = hexr,hexg,hexb
|
||||
else
|
||||
buf[#buf + 1] = "item_image_button[".. x*size + x_off ..",".. y*size + y_off ..";"..(size*size_increase)..","..(size*size_increase)..";hexcol:".. hexr .. hexg .. hexb ..";hexcol:".. hexr .. hexg .. hexb ..";]"
|
||||
end
|
||||
|
||||
end
|
||||
if (map_optimization) then
|
||||
if (temp_width>1) then
|
||||
buf[#buf + 1] = "item_image_button[".. old_x*size + x_off ..",".. y*size + y_off ..";"..(size)*(temp_width-2+size_increase)..","..(size*size_increase)..";hexcol:".. ohexr .. ohexg .. ohexb ..";hexcol:".. ohexr .. ohexg .. ohexb ..";]"
|
||||
temp_width = 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
buf[#buf + 1] = "vertlabel[".. x_off-0.3 ..",".. y_off + (height*size)/(string.len(y_axis)/1.3) ..";".. y_axis .."]"
|
||||
buf[#buf + 1] = "label[".. x_off + (width*size)/(string.len(x_axis)/1.3) ..",".. y_off+(height*size)+0.3 ..";".. x_axis .."]"
|
||||
buf[#buf + 1] = "vertlabel[".. x_off-0.3 ..",".. y_off + (height*size)/2 - string.len(y_axis)/7 ..";".. y_axis .."]"
|
||||
buf[#buf + 1] = "label[".. x_off + (width*size)/2 - string.len(x_axis)/15 ..",".. y_off+(height*size)+0.3 ..";".. x_axis .."]"
|
||||
return buf
|
||||
end
|
||||
|
||||
-- helper function
|
||||
local function TableConcat(t1,t2)
|
||||
for i=1,#t2 do
|
||||
t1[#t1+1] = t2[i]
|
||||
end
|
||||
return t1
|
||||
end
|
||||
|
||||
local function assemble_colorspace()
|
||||
-- stuff always in formspec
|
||||
|
@ -265,7 +187,7 @@ local function assemble_colorspace()
|
|||
local x_off,y_off = 1,0
|
||||
local fs2 = {}
|
||||
if (mapping_type_index == "1") then fs2 = Assemble_Map(x_off,y_off)
|
||||
else if (mapping_type_index == "2") then fs2 = assemble_sliders(x_off,y_off,6.5,1) end end
|
||||
else if (mapping_type_index == "2") then fs2 = assemble_sliders(x_off,y_off,6.5,0.8) end end
|
||||
TableConcat(fs, fs2);
|
||||
fs[#fs+1] = "container_end[]"
|
||||
fs[#fs+1] = "list[current_player;main;0.5,9;8,4]"
|
||||
|
@ -323,6 +245,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
end
|
||||
if (fields.saturation) then
|
||||
saturation = minetest.explode_scrollbar_event(fields.saturation).value
|
||||
if (dropdown_index == "1" and tonumber(saturation) > 15) then
|
||||
saturation = 15;
|
||||
end
|
||||
color_picker.show_formspec(player)
|
||||
end
|
||||
if (fields.mapping_type) then
|
||||
|
|
2
settingtypes.txt
Normal file
2
settingtypes.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
# I recommend not going higher than 128, even 64 is quite heavy.
|
||||
map_size (the color maps square dimensions) int 64
|
Loading…
Reference in a new issue