Download CommonLua/X/XColorPicker.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 28.3 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/X/XColorPicker.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/X/XColorPicker.lua
-
curl -L -o XColorPicker.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/X/XColorPicker.lua
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 |