|
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 |
|
|
|
|
|
|
|
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) |
|
|
|
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, |
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
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, |
|
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 |
|
|
|
|
|
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 |
|
|
|
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, 90 * 60, false, false) |
|
end |
|
end |
|
|
|
function XColorStrip:DrawBackground() |
|
end |
|
|
|
function XColorStrip:DrawWindow(clip_box) |
|
local content_box = self.content_box |
|
local arrows_size = self:ArrowsSize() |
|
|
|
|
|
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) |
|
|
|
|
|
XWindow.DrawWindow(self, clip_box) |
|
|
|
|
|
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)) |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
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, |
|
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) |
|
|
|
XWindow.DrawWindow(self, clip_rect) |
|
|
|
local content_box = self.content_box |
|
|
|
|
|
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)) |
|
|
|
|
|
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 |