myspace / CommonLua /X /XColorPicker.lua
sirnii's picture
Upload 1816 files
b6a38d7 verified
raw
history blame
28.3 kB
DefineClass.ColorPalette = {
__parents = {"Preset"},
properties = {
{id = "Group", editor = false, }
},
EditorMenubar = "Editors.Art",
EditorMenubarName = "Color Palette",
}
local color_palette_rows = 6
local color_palette_columns = 8
local color_palette_total = color_palette_rows * color_palette_columns
function ColorPalette:ColorsPlainObj()
local obj = {}
for i = 1, color_palette_total do
local p = "color" .. i
obj[p] = self[p]
end
for i = 1, color_palette_total do
local p = "text" .. i
obj[p] = self[p]
end
return obj
end
for i = 1, color_palette_total do
local category = "Row" .. ((i - 1) / color_palette_columns) + 1
table.insert(ColorPalette.properties, {
id = "color" .. i,
name = "Color " .. i,
editor = "color",
default = RGBA(0, 0, 0, 255),
category = category,
})
table.insert(ColorPalette.properties, {
id = "text" .. i,
name = "Text " .. i,
editor = "text",
translate = false,
default = "",
category = category,
})
end
if FirstLoad then
CurrentColorPalette = false
end
function OnMsg.ClassesBuilt()
CurrentColorPalette = CurrentColorPalette or ColorPalette:new({})
end
function OnMsg.DataLoaded()
CurrentColorPalette = Presets.ColorPalette and Presets.ColorPalette.Default and Presets.ColorPalette.Default[1] or CurrentColorPalette
end
function ColorPalette:OnPostSave()
CurrentColorPalette = Presets.ColorPalette and Presets.ColorPalette.Default and Presets.ColorPalette.Default[1] or CurrentColorPalette
end
--------------------- Color Picker code --------------------
local function GetColorMode(component)
if component == "HUE" or component == "SATURATION" or component == "BRIGHTNESS"then
return "HSV"
end
if component == "RED" or component == "GREEN" or component == "BLUE" then
return "RGB"
end
end
local ComponentShaderFlags = {
["RED"] = const.modColorPickerRed,
["GREEN"] = const.modColorPickerGreen,
["BLUE"] = const.modColorPickerBlue,
["SATURATION"] = const.modColorPickerSaturation,
["BRIGHTNESS"] = const.modColorPickerBrightness,
["HUE"] = const.modColorPickerHue,
["ALPHA"] = const.modColorPickerAlpha,
}
local function IsColorSame(a, b)
return a.RED == b.RED and a.BLUE == b.BLUE and a.GREEN == b.GREEN and a.ALPHA == b.ALPHA
and a.HUE == b.HUE and a.SATURATION == b.SATURATION and a.BRIGHTNESS == b.BRIGHTNESS
end
local function RecalculateHSVComponentsOf(color)
local h, s, v
if color.RED == 0 and color.GREEN == 0 and color.BLUE == 0 then
h, s, v = 0, 0, 0
else
h, s, v = UIL.RGBtoHSV(MulDivRound(color.RED, 255, 1000), MulDivRound(color.GREEN, 255, 1000), MulDivRound(color.BLUE, 255, 1000))
end
color.HUE = MulDivRound(h, 1000, 255)
color.SATURATION = MulDivRound(s, 1000, 255)
color.BRIGHTNESS = MulDivRound(v, 1000, 255)
end
local function RecalculateRGBComponentsOf(color)
-- hue 255 should be interpreted as 0
local hue = MulDivRound(color.HUE, 255, 1000)
if hue == 255 then hue = 0 end
local r, g, b = UIL.HSVtoRGB(hue, MulDivRound(color.SATURATION, 255, 1000), MulDivRound(color.BRIGHTNESS, 255, 1000))
color.RED = MulDivRound(r, 1000, 255)
color.GREEN = MulDivRound(g, 1000, 255)
color.BLUE = MulDivRound(b, 1000, 255)
end
local function GetRGBAComponentsIn255Of(color)
return MulDivRound(color.RED, 255, 1000), MulDivRound(color.GREEN, 255, 1000), MulDivRound(color.BLUE, 255, 1000), MulDivRound(color.ALPHA, 255 , 1000)
end
function ConvertColorFromText(value, prefer_dec)
local r, g, b, a = value:match("^([^,]+),([^,]+),([^,]+),([^,]+)")
if not r then
a = 255
r, g, b = value:match("^([^,]+),([^,]+),([^,]+)")
end
if not r then
local hex = value:match("^%s*0[xX]([0-9a-fA-F]+)")
if not hex then
hex = value:match("^%s*#([0-9a-fA-F]+)")
end
if hex and #hex > 0 then
local hex_value = tonumber(hex, 16)
if hex_value then
r, g, b, a = GetRGBA(hex_value)
if a == 0 and #hex <= 6 then
a = 255
end
end
end
end
if not r then
local hex_value = tonumber(value, prefer_dec and 10 or 16)
if hex_value then
r, g, b, a = GetRGBA(hex_value)
end
end
r, g, b, a = tonumber(r) or 0, tonumber(g) or 0, tonumber(b) or 0, tonumber(a) or 0
r = Clamp(r, 0, 255)
g = Clamp(g, 0, 255)
b = Clamp(b, 0, 255)
a = Clamp(a, 0, 255)
return RGBA(r, g, b, a)
end
DefineClass.XColorPicker = {
__parents = { "XControl", "XActionsHost" },
properties = {
{ category = "General", id = "AdditionalComponent", editor = "choice", default = "none", items = {"none", "alpha", "intensity"} },
{ category = "General", id = "ShowColorPalette", editor = "bool", default = true },
},
LayoutMethod = "HList",
Padding = box(5, 5, 5, 5),
BorderWidth = 1,
BorderColor = RGB(32, 32, 32),
Background = 0,
FocusedBackground = 0,
MaxHeight = 350,
selected_checkbox = false,
strip_color_component = false,
current_color = false, -- table
OnColorChanged = false,
RolloverMode = false,
}
function XColorPicker:UpdateCurrentlySelectedPaletteColor()
if not rawget(self, "PaletteGrid") then return end
local current_color = RGB(GetRGB(self:GetColor()))
for i = 1, color_palette_total do
local ctrl = self["idButtonColor" .. i]
if RGB(GetRGB(ctrl.Background)) == current_color then
ctrl.BorderColor = RGB(167, 167, 167)
else
ctrl.BorderColor = RGB(0, 0, 0)
end
end
end
function XColorPicker:Init(rollover_color_picker_mode)
local gedapp = rawget(_G, "g_GedApp")
local scale = (gedapp and gedapp.color_picker_scale or 100) * 10
self:SetScaleModifier(point(scale, scale))
self.current_color = {
RED = 0,
GREEN = 0,
BLUE = 0,
HUE = 0,
SATURATION = 0,
BRIGHTNESS = 0,
ALPHA = 1000,
}
XColorSquare:new({
Id = "idColorSquare",
MinWidth = 200,
MinHeight = 200,
Margins = box(2, 2, 2, 2),
Background = RGB(255, 255, 255),
OnColorChanged = function(square, color, double_click)
self:SetColorInternal(color)
if double_click then
self:Close()
end
end,
}, self)
XColorStrip:new({
Id = "idColorStrip",
MinWidth = 300,
MinHeight = 45,
slider_orientation = "horizontal",
OnColorChanged = function(stripe, color) self:UpdateComponent(self.strip_color_component, color[self.strip_color_component]) end
}, self):SetDock("bottom")
XColorStrip:new({
Id = "idAlphaStrip",
MinWidth = 45,
MinHeight = 200,
Margins = box(2, 2, 2, 2),
OnColorChanged = function(stripe, color) self:UpdateComponent("ALPHA", color.ALPHA) end
}, self):SetVisible(self.AdditionalComponent ~= "none")
if self.AdditionalComponent == "none" then
self.idAlphaStrip:SetDock("ignore")
end
XWindow:new({
Id = "idRightPanel",
LayoutMethod = "VList",
MinWidth = 150,
MinHeight = 200,
BorderColor = RGB(0, 0, 0),
BorderWidth = 0,
Padding = box(2, 0, 2, 0),
Pargins = box(2, 0, 0, 0),
}, self)
local color_palette = gedapp and gedapp.color_palette or CurrentColorPalette or false
XWindow:new({
Id = "PaletteGrid",
LayoutMethod = "VList",
BorderColor = RGB(0, 0, 0),
BorderWidth = 0,
Padding = box(2, 2, 2, 2),
}, self.idRightPanel)
for y = 1, color_palette_rows do
local row = XWindow:new({
LayoutMethod = "HList",
}, self.PaletteGrid)
for x = 1, color_palette_columns do
local color_idx = (x + (y - 1) * color_palette_columns)
local color = color_palette and color_palette["color" .. color_idx] or RGB(255,255,255)
local text = color_palette and color_palette["text" .. color_idx] or ""
XButton:new({
Id = "idButtonColor" .. color_idx,
Background = color,
RolloverBackground = color,
PressedBackground = color,
MinWidth = 30,
MinHeight = 20,
BorderColor = RGB(0, 0, 0),
RolloverBorderColor = RGB(32, 32, 32),
PressedBorderColor = RGB(64, 64, 64),
BorderWidth = 2,
Margins = box(2, 2, 2, 2),
OnPress = function()
self:SetColor(color)
end,
RolloverTranslate = false,
RolloverTemplate = "GedPropRollover",
RolloverTitle = text,
RolloverText = text,
}, row)
end
end
self:UpdateCurrentlySelectedPaletteColor()
XWindow:new({
Id = "idInputs",
LayoutMethod = "HPanel",
VAlign = "center",
HAlign = "center",
MinWidth = 300,
MinHeight = 200,
Padding = box(4, 2, 4, 2),
Background = RGBA(0, 0, 0, 0),
}, self.idRightPanel)
local left_inputs = XWindow:new({
Id = "left",
LayoutMethod = "VList",
MinWidth = 150,
}, self.idInputs)
local right_inputs = XWindow:new({
Id = "right",
LayoutMethod = "VList",
MinWidth = 150,
}, self.idInputs)
local hue_checkbox = self:MakeComponent({
idEdit = "idHue",
ComponentId = "HUE",
Name = "H",
Suffix = "°",
Max = 360,
focus_order = point(0, 0),
parent = left_inputs,
OnValueEdited = function(component_id, number) self:UpdateComponent(component_id, MulDivRound(number, 1000, 360)) end,
})
self:MakeComponent({
idEdit = "idSat",
ComponentId = "SATURATION",
Name = "S",
Suffix = "%",
Max = 100,
focus_order = point(0, 1),
parent = left_inputs,
OnValueEdited = function(component_id, number) self:UpdateComponent(component_id, MulDivRound(number, 1000, 100)) end,
})
self:MakeComponent({
idEdit = "idBri",
ComponentId = "BRIGHTNESS",
Name = "B",
Suffix = "%",
Max = 100,
focus_order = point(0, 2),
parent = left_inputs,
OnValueEdited = function(component_id, number) self:UpdateComponent(component_id, MulDivRound(number, 1000, 100)) end,
})
self:MakeComponent({
idEdit = "idRed",
ComponentId = "RED",
Name = "R",
Max = 255,
focus_order = point(0, 3),
parent = right_inputs,
OnValueEdited = function(component_id, number) self:UpdateComponent(component_id, MulDivRound(number, 1000, 255)) end,
Selectable = true,
})
self:MakeComponent({
idEdit = "idGreen",
ComponentId = "GREEN",
Name = "G",
Max = 255,
focus_order = point(0, 4),
parent = right_inputs,
OnValueEdited = function(component_id, number) self:UpdateComponent(component_id, MulDivRound(number, 1000, 255)) end,
})
self:MakeComponent({
idEdit = "idBlue",
ComponentId = "BLUE",
Name = "B",
Max = 255,
focus_order = point(0, 5),
parent = right_inputs,
OnValueEdited = function(component_id, number) self:UpdateComponent(component_id, MulDivRound(number, 1000, 255)) end,
})
if self.AdditionalComponent ~= "none" then
self:MakeComponent({
idEdit = "idAlpha",
parent = right_inputs,
ComponentId = "ALPHA",
Name = self.AdditionalComponent == "alpha" and "A" or "I",
Max = 255,
VSpacing = 0,
Selectable = false,
focus_order = point(0, 6),
OnValueEdited = function(component_id, number) self:UpdateComponent(component_id, MulDivRound(number, 1000, 255)) end,
})
end
local bottom_left = XWindow:new({
}, left_inputs)
local hex_value = XEdit:new({
Id = "idHexView",
HAlign = "stretch",
VAlign = "center",
}, bottom_left)
hex_value:SetText("0xFFFFFFFF")
local function RefetchHexValue()
local color_text = hex_value:GetText()
local color = ConvertColorFromText(color_text)
if color and color ~= self:GetColor() then
self:SetColor(color)
end
end
hex_value.OnKillFocus = function(self, ...)
RefetchHexValue()
return XEdit.OnKillFocus(self, ...)
end
hex_value.OnShortcut = function(self, shortcut, ...)
if shortcut == "Enter" then
RefetchHexValue()
return "break"
end
return XEdit.OnShortcut(self, shortcut, ...)
end
hex_value:SetAutoSelectAll(true)
if self.RolloverMode then
local button = XTemplateSpawn("GedToolbarButton", bottom_left)
button:SetDock("left")
button:SetHAlign("left")
button:SetVAlign("center")
button:SetIcon("CommonAssets/UI/Ged/filter.tga")
button:SetRolloverText("Pick color from game")
button.OnPress = function(b)
self.RolloverMode()
self:Done()
end
end
self:SetStripComponent("HUE", hue_checkbox)
self:UpdateDisplayedComponents()
end
function XColorPicker:UpdateComponent(component_id, value)
local new_color = table.copy(self.current_color)
new_color[component_id] = value
-- recalculate others fields that might have changed
local colorMode = GetColorMode(component_id)
if colorMode == "RGB" then
RecalculateHSVComponentsOf(new_color)
elseif colorMode == "HSV" then
RecalculateRGBComponentsOf(new_color)
end
self:SetColorInternal(new_color)
end
function XColorPicker:SetColorInternal(color)
if not IsColorSame(self.current_color, color) then
self.current_color = color
if self.OnColorChanged then
self:OnColorChanged(RGBA(GetRGBAComponentsIn255Of(color)))
end
self:UpdateDisplayedComponents()
self.idColorSquare:SetColor(color)
self.idColorStrip:SetColor(color)
self.idAlphaStrip:SetColor(color)
self:UpdateCurrentlySelectedPaletteColor()
end
end
function XColorPicker:GetColor()
return RGBA(GetRGBAComponentsIn255Of(self.current_color))
end
function XColorPicker:SetColor(color)
color = color or RGBA(0, 0, 0, 0)
local r, g, b, a = GetRGBA(color)
local new_color = {
RED = MulDivRound(r, 1000, 255),
GREEN = MulDivRound(g, 1000, 255),
BLUE = MulDivRound(b, 1000, 255),
ALPHA = MulDivRound(a, 1000, 255),
}
RecalculateHSVComponentsOf(new_color)
self:SetColorInternal(new_color)
end
function XColorPicker:UpdateDisplayedComponents()
local color = self.current_color
self.idHue:SetText(tostring(MulDivRound(color.HUE, 360, 1000)))
self.idSat:SetText(tostring(MulDivRound(color.SATURATION, 1, 10)))
self.idBri:SetText(tostring(MulDivRound(color.BRIGHTNESS, 1, 10)))
self.idRed:SetText(tostring(MulDivRound(color.RED, 255, 1000)))
self.idGreen:SetText(tostring(MulDivRound(color.GREEN, 255, 1000)))
self.idBlue:SetText(tostring(MulDivRound(color.BLUE, 255, 1000)))
self.idHexView:SetText(string.format("0x%08X", self:GetColor()))
if self.AdditionalComponent ~= "none" then
self.idAlpha:SetText(tostring(MulDivRound(color.ALPHA, 255, 1000)))
end
end
function XColorPicker:SetStripComponent(id, control)
if self.selected_checkbox then
self.selected_checkbox:SetCheck(false)
end
control:SetCheck(true)
self.selected_checkbox = control
self.strip_color_component = id
self.idColorSquare:SetConstantColorComponent(id)
self.idColorStrip:SetEditedColorComponent(id)
self.idAlphaStrip:SetEditedColorComponent("ALPHA")
self:UpdateDisplayedComponents()
end
function XColorPicker:MakeComponent(params)
params.Min = params.Min or 0
params.Max = params.Max or 255
params.Selectable = params.Selectable ~= false
local parent = XWindow:new({
Margins = box(0, 0, 0, params.VSpacing or 10),
}, params.parent)
local check_box = XCheckButton:new({
Dock = "left",
VAlign = "center",
OnChange = function(control, check)
self:SetStripComponent(params.ComponentId, control)
end,
}, parent)
if not params.Selectable then
check_box:SetVisible(false)
end
XLabel:new({
Dock = "left",
VAlign = "center",
}, parent):SetText(params.Name .. ":")
XLabel:new({
Dock = "right",
VAlign = "center",
MinWidth = 25,
}, parent):SetText(params.Suffix or "")
CreateNumberEditor(
XWindow:new({
Dock = "box",
VAlign = "center",
}, parent),
params.idEdit,
function(multiplier)
local value = tonumber(self[params.idEdit]:GetText()) or 0
params.OnValueEdited(params.ComponentId, Clamp(value + multiplier, params.Min, params.Max))
end,
function(multiplier)
local value = tonumber(self[params.idEdit]:GetText()) or 0
params.OnValueEdited(params.ComponentId, Clamp(value - multiplier, params.Min, params.Max))
end
)
local edit_control = self[params.idEdit]
edit_control:SetFocusOrder(params.focus_order or point(0, 0))
edit_control.OnKillFocus = function(self)
if self then
local value = tonumber(edit_control:GetText()) or 0
params.OnValueEdited(params.ComponentId, Clamp(value, params.Min, params.Max))
XEdit.OnKillFocus(self)
end
end
return check_box
end
---- Strip color picker
DefineClass.XColorStrip = {
__parents = { "XControl" },
Padding = box(2, 2, 2, 2),
BorderWidth = 1,
BorderColor = RGBA(32, 32, 32, 255),
Background = RGBA(0, 0, 0, 0),
slider_orientation = "vertical",
slider_color = RGB(32, 32, 32),
slider_size = point(10, 20),
slider_image_right = "CommonAssets/UI/arrowright-40.tga",
slider_image_left = "CommonAssets/UI/arrowleft-40.tga",
slider_image_down = "CommonAssets/UI/arrowdown-40.tga",
slider_image_up = "CommonAssets/UI/arrowup-40.tga",
slider_image_srect = box(0, 0, 16, 40),
slider_image_srect_horizontal = box(0, 0, 40, 16),
strip_background_image = "CommonAssets/UI/checker-pattern-40.tga",
gradient_modifier = false,
strip_color_component = false,
current_color = false, -- table
OnColorChanged = false,
}
function XColorStrip:Init()
self.current_color = {
RED = 0,
GREEN = 0,
BLUE = 0,
HUE = 0,
SATURATION = 0,
BRIGHTNESS = 0,
ALPHA = 1000,
}
self.gradient_modifier = self:AddShaderModifier({
modifier_type = const.modShader,
})
end
function XColorStrip:OnMouseButtonDown(pt, button)
if button == "L" then
self.desktop:SetMouseCapture(self)
self:OnMousePos(pt)
return "break"
end
end
function XColorStrip:OnMouseButtonUp(pt, button)
if button == "L" then
self:OnMousePos(pt)
self.desktop:SetMouseCapture()
return "break"
end
end
function XColorStrip:OnMousePos(pt)
if self.desktop:GetMouseCapture() ~= self then return "break" end
local content_box = self.content_box
local percent
if self.slider_orientation == "vertical" then
percent = 1000 - Clamp(MulDivRound(pt:y() - content_box:miny(), 1000, content_box:sizey()), 0, 1000)
else
percent = 1000 - Clamp(MulDivRound(pt:x() - content_box:minx(), 1000, content_box:sizex()), 0, 1000)
end
local new_color = table.copy(self.current_color)
new_color[self.strip_color_component] = percent
if GetColorMode(self.strip_color_component) == "RGB" then
RecalculateHSVComponentsOf(new_color)
else
RecalculateRGBComponentsOf(new_color)
end
self:SetColor(new_color)
if self.OnColorChanged then
self:OnColorChanged(new_color)
end
self:Invalidate()
return "break"
end
function XColorStrip:SetColor(color)
if not IsColorSame(self.current_color, color) then
self.current_color = color
self:UpdateGradientModifier()
end
end
function XColorStrip:SetEditedColorComponent(component)
if self.strip_color_component ~= component then
self.strip_color_component = component
self:UpdateGradientModifier()
end
end
function XColorStrip:GetEditedColorComponent()
return self.current_color[self.strip_color_component]
end
function XColorStrip:UpdateGradientModifier()
self.gradient_modifier.shader_flags = const.modColorPickerStrip | ComponentShaderFlags[self.strip_color_component]
local modifier = self.gradient_modifier
local color = self.current_color
if GetColorMode(self.strip_color_component) == "RGB" or self.strip_color_component == "ALPHA" then
modifier[1] = color.RED
modifier[2] = color.GREEN
modifier[3] = color.BLUE
modifier[4] = color.ALPHA
elseif self.strip_color_component == "HUE" then
modifier[1] = 1000
modifier[2] = 1000
modifier[3] = 1000
modifier[4] = 1000
else
modifier[1] = color.HUE
modifier[2] = color.SATURATION
modifier[3] = color.BRIGHTNESS
modifier[4] = color.ALPHA
end
self:Invalidate()
end
local PushClipRect = UIL.PushClipRect
local PopClipRect = UIL.PopClipRect
function XColorStrip:ArrowsSize()
local arrows_size = point(ScaleXY(self.scale, self.slider_size:x(), self.slider_size:y()))
if self.slider_orientation ~= "vertical" then
arrows_size = point(arrows_size:y(), arrows_size:x())
end
return arrows_size
end
function XColorStrip:GetStripBox()
local arrows_size = self:ArrowsSize()
local content_box = self.content_box
local strip_box
if self.slider_orientation == "vertical" then
strip_box = box(content_box:minx() + arrows_size:x(), content_box:miny(), content_box:maxx() - arrows_size:x(), content_box:maxy())
else
strip_box = box(content_box:minx(), content_box:miny() + arrows_size:y(), content_box:maxx(), content_box:maxy() - arrows_size:y())
end
return strip_box
end
-- DrawContent is called with modifiers enabled so the solid rect will actually be a gradient
function XColorStrip:DrawContent(clip_box)
local strip_box = self:GetStripBox()
if self.slider_orientation == "vertical" then
UIL.DrawSolidRect(strip_box, RGBA(255, 255, 255, 255), RGBA(0, 0, 0, 0), point(1000, 1000), point(0, 0))
else
-- we use drawimagefit as it has all the properties we need, checker-pattern-40 is loaded anyway for the background.
local w, h = UIL.MeasureImage("CommonAssets/UI/checker-pattern-40.tga")
local center = strip_box:min() + strip_box:size() / 2
local top_left = center - point(strip_box:sizey() / 2, strip_box:sizex() / 2)
local rotated_box = sizebox(top_left:x(), top_left:y(), strip_box:sizey(), strip_box:sizex())
UIL.DrawImageFit("CommonAssets/UI/checker-pattern-40.tga", rotated_box, rotated_box:sizex(), rotated_box:sizey(), box(0,0,w,h), RGB(255,255,255),
0, --[[angle]] 90 * 60, --[[flips]] false, false)
end
end
function XColorStrip:DrawBackground()
end
function XColorStrip:DrawWindow(clip_box)
local content_box = self.content_box
local arrows_size = self:ArrowsSize()
-- draw the checkers background for alpha values
local strip_box = self:GetStripBox()
UIL.DrawFrame(self.strip_background_image, strip_box, 1, 1, 1, 1, box(0, 0, 0, 0), false, false, 350, 350, false, false)
-- draw gradient
XWindow.DrawWindow(self, clip_box)
-- draw border
local border_width, border_height = ScaleXY(self.scale, self.BorderWidth, self.BorderWidth)
local border_box = GrowBox(strip_box, border_width)
UIL.DrawBorderRect(border_box, border_width, border_height, self:CalcBorderColor(), RGBA(0, 0, 0, 0))
-- draw the selection
local weight = 1000 - Clamp(self:GetEditedColorComponent(), 0, 1000)
if self.slider_orientation == "vertical" then
local sliderY = content_box:miny() + MulDivRound(weight, content_box:sizey(), 1000)
local left_arrow = sizebox(content_box:minx(), sliderY - arrows_size:y() / 2, arrows_size:x(), arrows_size:y())
local right_arrow = sizebox(content_box:maxx() - arrows_size:x(), sliderY - arrows_size:y() / 2, arrows_size:x(), arrows_size:y())
UIL.DrawImageFit(self.slider_image_right, left_arrow, arrows_size:x(), arrows_size:y(), self.slider_image_srect, self.slider_color, 0)
UIL.DrawImageFit(self.slider_image_left, right_arrow, arrows_size:x(), arrows_size:y(), self.slider_image_srect, self.slider_color, 0)
else
local sliderX = content_box:minx() + MulDivRound(weight, content_box:sizex(), 1000)
local up_arrow = sizebox(sliderX - arrows_size:x() / 2, content_box:miny(), arrows_size:x(), arrows_size:y())
local down_arrow = sizebox(sliderX - arrows_size:x() / 2, content_box:maxy() - arrows_size:y(), arrows_size:x(), arrows_size:y())
UIL.DrawImageFit(self.slider_image_down, up_arrow, arrows_size:x(), arrows_size:y(), self.slider_image_srect_horizontal, self.slider_color, 0)
UIL.DrawImageFit(self.slider_image_up, down_arrow, arrows_size:x(), arrows_size:y(), self.slider_image_srect_horizontal, self.slider_color, 0)
end
end
--- Square color picker
DefineClass.XColorSquare = {
__parents = { "XControl" },
Clip = "parent & self",
Padding = box(2, 2, 2, 2),
BorderWidth = 1,
BorderColor = RGB(32, 32, 32),
Background = RGB(255, 255, 255),
slider_color = RGB(128, 128, 128),
slider_size = point(20, 20),
slider_image = "CommonAssets/UI/circle-20.tga",
gradient_modifier = false,
constant_color_component = false,
edited_component_id1 = false,
edited_component_id2 = false,
current_color = false, -- table
OnColorChanged = false,
}
function XColorSquare:Init()
self.current_color = {
RED = 0,
GREEN = 0,
BLUE = 0,
HUE = 0,
SATURATION = 0,
BRIGHTNESS = 0,
ALPHA = 1000,
}
self.gradient_modifier = self:AddShaderModifier({
modifier_type = const.modShader,
})
end
function XColorSquare:Measure(max_width, max_height)
local size = Min(max_width, max_height)
return size, size
end
function XColorSquare:OnMouseButtonDown(pt, button)
if button == "L" then
self.desktop:SetMouseCapture(self)
self:OnMousePos(pt)
return "break"
end
end
function XColorSquare:OnMouseButtonUp(pt, button)
if button == "L" then
self:OnMousePos(pt)
self.desktop:SetMouseCapture()
return "break"
end
end
function XColorSquare:OnMousePos(pt)
if self.desktop:GetMouseCapture() ~= self then return "break" end
local content_box = self.content_box
local percent_x = 1000 - Clamp((pt:x() - content_box:minx()) * 1000 / content_box:sizex(), 0, 1000)
local percent_y = 1000 - Clamp((pt:y() - content_box:miny()) * 1000 / content_box:sizey(), 0, 1000)
local new_color = table.copy(self.current_color)
new_color[self.edited_component_id1] = percent_x
new_color[self.edited_component_id2] = percent_y
if GetColorMode(self.constant_color_component) == "RGB" then
RecalculateHSVComponentsOf(new_color)
else
RecalculateRGBComponentsOf(new_color)
end
self:SetColor(new_color)
if self.OnColorChanged then
self:OnColorChanged(new_color)
end
return "break"
end
function XColorSquare:OnMouseButtonDoubleClick(pt, button)
if self.OnColorChanged then
self:OnColorChanged(self.current_color, true)
end
return "break"
end
function XColorSquare:SetColor(color)
if not IsColorSame(self.current_color, color) then
self.current_color = color
self:UpdateGradientModifier()
end
end
function XColorSquare:SetConstantColorComponent(component)
if self.constant_color_component ~= component then
self.constant_color_component = component
if component == "RED" then
self.edited_component_id1, self.edited_component_id2 = "GREEN", "BLUE"
elseif component == "GREEN" then
self.edited_component_id1, self.edited_component_id2 = "RED", "BLUE"
elseif component == "BLUE" then
self.edited_component_id1, self.edited_component_id2 = "RED", "GREEN"
elseif component == "HUE" then
self.edited_component_id1, self.edited_component_id2 = "SATURATION", "BRIGHTNESS"
elseif component == "SATURATION" then
self.edited_component_id1, self.edited_component_id2 = "HUE", "BRIGHTNESS"
elseif component == "BRIGHTNESS" then
self.edited_component_id1, self.edited_component_id2 = "HUE", "SATURATION"
end
self:UpdateGradientModifier()
end
end
function XColorSquare:GetEditedColorComponents()
return self.current_color[self.edited_component_id1], self.current_color[self.edited_component_id2]
end
function XColorSquare:UpdateGradientModifier()
self.gradient_modifier.shader_flags = const.modColorPickerSquare | ComponentShaderFlags[self.constant_color_component]
local modifier = self.gradient_modifier
local color = self.current_color
if GetColorMode(self.constant_color_component) == "RGB" then
modifier[1] = color.RED
modifier[2] = color.GREEN
modifier[3] = color.BLUE
modifier[4] = color.ALPHA
else
modifier[1] = color.HUE
modifier[2] = color.SATURATION
modifier[3] = color.BRIGHTNESS
modifier[4] = color.ALPHA
end
end
function XColorSquare:DrawBackground()
end
function XColorSquare:DrawContent(clip_rect)
UIL.DrawSolidRect(self.content_box, RGBA(255, 255, 255, 255), RGBA(0, 0, 0, 0), point(1000, 1000), point(0, 0))
end
function XColorSquare:DrawWindow(clip_rect)
-- draw the gradient
XWindow.DrawWindow(self, clip_rect)
local content_box = self.content_box
-- draw border
local border_width, border_height = ScaleXY(self.scale, self.BorderWidth, self.BorderWidth)
local border_box = GrowBox(content_box, border_width)
UIL.DrawBorderRect(border_box, border_width, border_height, self:CalcBorderColor(), RGBA(0, 0, 0, 0))
-- draw the selection
PushClipRect(content_box, true)
local x, y = self:GetEditedColorComponents()
local weight_x = 1000 - Clamp(x, 0, 1000)
local weight_y = 1000 - Clamp(y, 0, 1000)
local slider_pos = point(content_box:minx() + weight_x * content_box:sizex() / 1000, content_box:miny() + weight_y * content_box:sizey() / 1000)
local slider_size = point(ScaleXY(self.scale, self.slider_size:x(), self.slider_size:y()))
local slider_box = sizebox(slider_pos - slider_size / 2, slider_size)
local circle_color = self.current_color.BRIGHTNESS < 500 and RGB(200, 200, 200) or RGB(32, 32, 32)
UIL.DrawImageFit(self.slider_image, slider_box, slider_size:x(), slider_size:y(), box(0, 0, self.slider_size:x(), self.slider_size:y()), circle_color, 0)
PopClipRect()
end