--- @type StdUi local StdUi = LibStub and LibStub('StdUi', true); if not StdUi then return end local module, version = 'ColorPicker', 6; if not StdUi:UpgradeNeeded(module, version) then return end local ColorPickerMethods = { SetColorRGBA = function(self, r, g, b, a) self:SetColorAlpha(a); self:SetColorRGB(r, g, b); self.newTexture:SetVertexColor(r, g, b, a); end, GetColorRGBA = function(self) local r, g, b = self:GetColorRGB(); return r, g, b, self:GetColorAlpha(); end, SetColor = function(self, c) self:SetColorAlpha(c.a or 1); self:SetColorRGB(c.r, c.g, c.b); self.newTexture:SetVertexColor(c.r, c.g, c.b, c.a or 1); end, GetColor = function(self) local r, g, b = self:GetColorRGB(); return { r = r, g = g, b = b, a = self:GetColorAlpha() }; end, SetColorAlpha = function(self, a, fromSlider) a = Clamp(a, 0, 1); if not fromSlider then self.alphaSlider:SetValue(100 - a * 100); end self.aEdit:SetValue(Round(a * 100)); self.aEdit:Validate(); self:SetColorRGB(self:GetColorRGB()); end, GetColorAlpha = function(self) local a = Clamp(tonumber(self.aEdit:GetValue()) or 100, 0, 100); return a / 100; end }; local ColorPickerEvents = { OnColorSelect = function(self) -- Ensure custom fields are updated. local r, g, b, a = self:GetColorRGBA(); if not self.skipTextUpdate then self.rEdit:SetValue(r * 255); self.gEdit:SetValue(g * 255); self.bEdit:SetValue(b * 255); self.aEdit:SetValue(100 * a); self.rEdit:Validate(); self.gEdit:Validate(); self.bEdit:Validate(); self.aEdit:Validate(); end self.newTexture:SetVertexColor(r, g, b, a); self.alphaTexture:SetGradientAlpha('VERTICAL', 1, 1, 1, 0, r, g, b, 1); end }; local function OnColorPickerValueChanged(self) local cpf = self:GetParent(); local r = tonumber(cpf.rEdit:GetValue() or 255) / 255; local g = tonumber(cpf.gEdit:GetValue() or 255) / 255; local b = tonumber(cpf.bEdit:GetValue() or 255) / 255; local a = tonumber(cpf.aEdit:GetValue() or 100) / 100; cpf.skipTextUpdate = true; cpf:SetColorRGB(r, g, b); cpf.alphaSlider:SetValue(100 - a * 100); cpf.skipTextUpdate = false; end --- alphaSliderTexture = [[Interface\AddOns\YourAddon\Libs\StdUi\media\Checkers.tga]] function StdUi:ColorPicker(parent, alphaSliderTexture) local wheelWidth = 128; local thumbWidth = 10; local barWidth = 16; local cpf = CreateFrame('ColorSelect', nil, parent); --self:MakeDraggable(cpf); cpf:SetPoint('CENTER'); self:ApplyBackdrop(cpf, 'panel'); self:SetObjSize(cpf, 340, 200); -- Create colorpicker wheel. cpf.wheelTexture = self:Texture(cpf, wheelWidth, wheelWidth); self:GlueTop(cpf.wheelTexture, cpf, 10, -10, 'LEFT'); cpf.wheelThumbTexture = self:Texture(cpf, thumbWidth, thumbWidth, [[Interface\Buttons\UI-ColorPicker-Buttons]]); cpf.wheelThumbTexture:SetTexCoord(0, 0.15625, 0, 0.625); -- Create the colorpicker slider. cpf.valueTexture = self:Texture(cpf, barWidth, wheelWidth); self:GlueRight(cpf.valueTexture, cpf.wheelTexture, 10, 0); cpf.valueThumbTexture = self:Texture(cpf, barWidth, thumbWidth, [[Interface\Buttons\UI-ColorPicker-Buttons]]); cpf.valueThumbTexture:SetTexCoord(0.25, 1, 0.875, 0); cpf:SetColorWheelTexture(cpf.wheelTexture); cpf:SetColorWheelThumbTexture(cpf.wheelThumbTexture); cpf:SetColorValueTexture(cpf.valueTexture); cpf:SetColorValueThumbTexture(cpf.valueThumbTexture); cpf.alphaSlider = CreateFrame('Slider', nil, cpf); cpf.alphaSlider:SetOrientation('VERTICAL'); cpf.alphaSlider:SetMinMaxValues(0, 100); cpf.alphaSlider:SetValue(0); self:SetObjSize(cpf.alphaSlider, barWidth, wheelWidth + thumbWidth); -- hack self:GlueRight(cpf.alphaSlider, cpf.valueTexture, 10, 0); cpf.alphaTexture = self:Texture(cpf.alphaSlider, nil, nil, alphaSliderTexture); self:GlueAcross(cpf.alphaTexture, cpf.alphaSlider, 0, -thumbWidth / 2, 0, thumbWidth / 2); -- hack --cpf.alphaTexture:SetColorTexture(1, 1, 1, 1); --cpf.alphaTexture:SetGradientAlpha('VERTICAL', 0, 0, 0, 1, 1, 1, 1, 1); cpf.alphaThumbTexture = self:Texture(cpf.alphaSlider, barWidth, thumbWidth, [[Interface\Buttons\UI-ColorPicker-Buttons]]); cpf.alphaThumbTexture:SetTexCoord(0.275, 1, 0.875, 0); cpf.alphaThumbTexture:SetDrawLayer('ARTWORK', 2); cpf.alphaSlider:SetThumbTexture(cpf.alphaThumbTexture); cpf.newTexture = self:Texture(cpf, 32, 32, [[Interface\Buttons\WHITE8X8]]); cpf.oldTexture = self:Texture(cpf, 32, 32, [[Interface\Buttons\WHITE8X8]]); cpf.newTexture:SetDrawLayer('ARTWORK', 5); cpf.oldTexture:SetDrawLayer('ARTWORK', 4); self:GlueTop(cpf.newTexture, cpf, -30, -30, 'RIGHT'); self:GlueBelow(cpf.oldTexture, cpf.newTexture, 20, 45); ---------------------------------------------------- --- Buttons ---------------------------------------------------- cpf.rEdit = self:NumericBox(cpf, 60, 20); cpf.gEdit = self:NumericBox(cpf, 60, 20); cpf.bEdit = self:NumericBox(cpf, 60, 20); cpf.aEdit = self:NumericBox(cpf, 60, 20); cpf.rEdit:SetMinMaxValue(0, 255); cpf.gEdit:SetMinMaxValue(0, 255); cpf.bEdit:SetMinMaxValue(0, 255); cpf.aEdit:SetMinMaxValue(0, 100); self:AddLabel(cpf, cpf.rEdit, 'R', 'LEFT'); self:AddLabel(cpf, cpf.gEdit, 'G', 'LEFT'); self:AddLabel(cpf, cpf.bEdit, 'B', 'LEFT'); self:AddLabel(cpf, cpf.aEdit, 'A', 'LEFT'); self:GlueAfter(cpf.rEdit, cpf.alphaSlider, 20, -thumbWidth / 2); self:GlueBelow(cpf.gEdit, cpf.rEdit, 0, -10); self:GlueBelow(cpf.bEdit, cpf.gEdit, 0, -10); self:GlueBelow(cpf.aEdit, cpf.bEdit, 0, -10); cpf.okButton = StdUi:Button(cpf, 100, 20, OKAY); cpf.cancelButton = StdUi:Button(cpf, 100, 20, CANCEL); self:GlueBottom(cpf.okButton, cpf, 40, 20, 'LEFT'); self:GlueBottom(cpf.cancelButton, cpf, -40, 20, 'RIGHT'); ---------------------------------------------------- --- Methods ---------------------------------------------------- for k, v in pairs(ColorPickerMethods) do cpf[k] = v; end ---------------------------------------------------- --- Events ---------------------------------------------------- cpf.alphaSlider:SetScript('OnValueChanged', function(slider) cpf:SetColorAlpha((100 - slider:GetValue()) / 100, true); end); for k, v in pairs(ColorPickerEvents) do cpf:SetScript(k, v); end cpf.rEdit.OnValueChanged = OnColorPickerValueChanged; cpf.gEdit.OnValueChanged = OnColorPickerValueChanged; cpf.bEdit.OnValueChanged = OnColorPickerValueChanged; cpf.aEdit.OnValueChanged = OnColorPickerValueChanged; return cpf; end local ColorPickerFrameOkCallback = function(self) local cpf = self:GetParent(); if cpf.okCallback then cpf.okCallback(cpf); end cpf:Hide(); end local ColorPickerFrameCancelCallback = function(self) local cpf = self:GetParent(); if cpf.cancelCallback then cpf.cancelCallback(cpf); end cpf:Hide(); end -- placeholder function StdUi:ColorPickerFrame(r, g, b, a, okCallback, cancelCallback, alphaSliderTexture) local colorPickerFrame = self.colorPickerFrame; if not colorPickerFrame then colorPickerFrame = self:ColorPicker(UIParent, alphaSliderTexture); colorPickerFrame:SetFrameStrata('FULLSCREEN_DIALOG'); self.colorPickerFrame = colorPickerFrame; end colorPickerFrame.okCallback = okCallback; colorPickerFrame.cancelCallback = cancelCallback; colorPickerFrame.okButton:SetScript('OnClick', ColorPickerFrameOkCallback); colorPickerFrame.cancelButton:SetScript('OnClick', ColorPickerFrameCancelCallback); colorPickerFrame:SetColorRGBA(r or 1, g or 1, b or 1, a or 1); colorPickerFrame.oldTexture:SetVertexColor(r or 1, g or 1, b or 1, a or 1); colorPickerFrame:ClearAllPoints(); colorPickerFrame:SetPoint('CENTER'); colorPickerFrame:Show(); end local ColorInputMethods = { SetColor = function(self, c) if type(c) == 'table' then self.color.r = c.r; self.color.g = c.g; self.color.b = c.b; self.color.a = c.a or 1; end self.target:SetBackdropColor(c.r, c.g, c.b, c.a or 1); if self.OnValueChanged then self:OnValueChanged(c); end end, GetColor = function (self, type) if type == 'hex' then elseif type == 'rgba' then return self.color.r, self.color.g, self.color.b, self.color.a else -- object return self.color; end end }; local ColorInputEvents = { OnClick = function(self) self.stdUi:ColorPickerFrame( self.color.r, self.color.g, self.color.b, self.color.a, function(cpf) self:SetColor(cpf:GetColor()); end ); end }; function StdUi:ColorInput(parent, label, width, height, color) local button = CreateFrame('Button', nil, parent); button.stdUi = self; button:EnableMouse(true); self:SetObjSize(button, width, height or 20); self:InitWidget(button); button.target = self:Panel(button, 16, 16); button.target.stdUi = self; button.target:SetPoint('LEFT', 0, 0); button.text = self:Label(button, label); button.text:SetPoint('LEFT', button.target, 'RIGHT', 5, 0); button.text:SetPoint('RIGHT', button, 'RIGHT', -5, 0); button.color = {r = 1, g = 1, b = 1, a = 1}; if not button.SetBackdrop then Mixin(button, BackdropTemplateMixin) end self:HookDisabledBackdrop(button); --ColorInput has no visual difference when disabled unlike Checkbox self:HookHoverBorder(button); for k, v in pairs(ColorInputMethods) do button[k] = v; end for k, v in pairs(ColorInputEvents) do button:SetScript(k, v); end if color then button:SetColor(color); end return button; end StdUi:RegisterModule(module, version);