WoWInterface (
-   Lua/XML Help (
-   -   Coloring standard buttons (

Billtopia 01-10-13 10:13 AM

Coloring standard buttons
What is the best way ( or is there more than one ) to change a buttons color from the standard WoW red to green (or whatever) if the option it toggles is enabled or not... For example I have a list of people that is generated from the real-id / battle-tag friends list. The addon puts asterisks around the names that it is selected to alert for... I was wondering if I could change the button colors as well to make it easier to differentiate the enabled ones from the non-enabled? I searched the web and here but I don't think I found what I was looking for...

Seerah 01-10-13 04:31 PM

The button you are seeing isn't colored at all (well, technically, it's colored white). It's a texture. If you try to color it green, it will turn into some greenish-red color.

You can... change the color of the text on the button, change the texture of the button, or use some other method to display your info. (edit: unless you want the greenish-red color)

Billtopia 01-10-13 04:40 PM

OK... that is what I feared... lol I guess I will have to figure a way to change the textures when I update the text on them (it is a virtual scrolling list that activates and deactivates alerts on a per real-id / battle-tag basis) I suppose it is about time I figured out some more advanced stuff lol

Billtopia 01-12-13 08:40 PM

ok... so I have these nice green button textures... (recolored red ones from wow) and they do not cover the whole button, and I cant tell wow to SetTexCoord them as they are set by SetPushedTexture, SetNormalTexture, SetHighlightTexture...

So, what am I missing...

Phanx 01-12-13 08:41 PM


Billtopia 01-12-13 08:43 PM

sweet... you are a WoW Lua GOD and I kneel at your feet :)

Billtopia 01-13-13 09:52 AM

2 Attachment(s)
so I have the buttons changing textures now... but it looks like in earlier versions of WoW when you made a large button (all stretched and miss formed)

default red button Attachment 7501

my green button Attachment 7500

am I doing something wrong here? or am I missing something?

Lua Code:
  1. me.ListButtons[x]:SetText( "*** "..Table[x + slider].fullName.." ***" )
  2. me.ListButtons[x]:SetHighlightTexture("Interface\\AddOns\\NickAlert\\Green-Panel-Button-Highlight.tga")
  3. me.ListButtons[x]:GetHighlightTexture():SetTexCoord( 0, 0.625, 0, 0.6875 )
  4. me.ListButtons[x]:SetNormalTexture("interface\\addons\\nickalert\\green-panel-button-up.tga")
  5. me.ListButtons[x]:GetNormalTexture():SetTexCoord( 0, 0.625, 0, 0.6875 )
  6. me.ListButtons[x]:SetPushedTexture("Interface\\AddOns\\NickAlert\\Green-Panel-Button-Down.tga")
  7. me.ListButtons[x]:GetPushedTexture():SetTexCoord( 0, 0.625, 0, 0.6875 )
I also noticed that the textures appear OVER the WoW default texture (and SetNormalTexture( nil ) and SetPushedTexture( nil ) return them to default but SetHighlightTexture( nil ) removes the highlight texture all together)

Phanx 01-13-13 05:53 PM

You should just place the recolored texture file in the appropriate path in your WoW folder so it overwrites the default texture file automatically. See PinkButtons for an example.

Billtopia 01-13-13 06:56 PM

I only want the button green some of the time... like to indicate when that option is enabled

Phanx 01-13-13 11:13 PM

Well, you've never specified which button(s) you want to recolor, but assuming they inherit from the UIPanelButtonTemplate, they don't use the normal texture and pushed texture. Instead, they have separate left/right/center texture regions (to accomodate different widths without distorting the texture too much) and the textures are swapped OnMouseDown and OnMouseUp.


You'd need to HookScript each method that sets textures, and set your own texture in the post-hook, or just overwrite the relevant methods (though you'd need to be careful to avoid tainting or breaking anything, so simple overwriting might not be an option for some buttons).

Billtopia 01-14-13 07:36 AM

OMG!!! Blizz is sick... Why not make a method that allows you to map the stretching portions of a texture... it would take 3 args... like HTexStretch( 15, 70, 15 ) telling it not to stretch the 1st and last % but it can stretch the middle %...

Guess I will copy that section of the XML... make a new file... and mod it a bit... and inherit it into my buttons and see what happens.

I know I should just live with the stretched textures though lol

Phanx 01-14-13 07:17 PM

Such a method would just be an alias for what Blizzard is already doing, similar to how frame:SetHighlightTexture(path) is basically just an alias for:

local highlight = frame:CreateTexture(nil, "HIGHLIGHT")

It would also be far less flexible than just slicing up the texture yourself.

Billtopia 01-14-13 08:29 PM

so this is what I got... and it works :) you just inherit the template into your button and set the color by ButtonVar.color = "red" or ButtonVar.color = "green" I know I need to put some checks in for wrong colors

another thing... be gentle, this is my first xml lol

and with your example, I see what you mean as you can customize the textures better in the longer method than trying to use a shortcut...

I have to thank you again for your help


<?xml version="1.0" encoding="utf-8"?>
<Ui xmlns:xsi="" xmlns="" xsi:schemaLocation="
    <Button name="RedGreenButtonTemplate" virtual="true">
        <Size x="40" y="22"/>
            <Layer level="BACKGROUND">
                <Texture parentKey="Left" file="Interface\Buttons\UI-Panel-Button-Up">
                    <Size x="12" y="22"/>
                        <Anchor point="TOPLEFT"/>
                        <Anchor point="BOTTOMLEFT"/>
                    <TexCoords left="0" right="0.09375" top="0" bottom="0.6875"/>
                <Texture parentKey="Right" file="Interface\Buttons\UI-Panel-Button-Up">
                    <Size x="12" y="22"/>
                        <Anchor point="TOPRIGHT"/>
                        <Anchor point="BOTTOMRIGHT"/>
                    <TexCoords left="0.53125" right="0.625" top="0" bottom="0.6875"/>
                <Texture parentKey="Middle" file="Interface\Buttons\UI-Panel-Button-Up">
                    <Size x="12" y="22"/>
                        <Anchor point="TOPLEFT" relativeKey="$parent.Left" relativePoint="TOPRIGHT"/>
                        <Anchor point="BOTTOMRIGHT" relativeKey="$parent.Right" relativePoint="BOTTOMLEFT"/>
                    <TexCoords left="0.09375" right="0.53125" top="0" bottom="0.6875"/>
                self.displayedColor = "red"
                self.color = "red"
                self.skins = {}
       = {}
       = "Interface\\Buttons\\UI-Panel-Button-Up"
       = "Interface\\Buttons\\UI-Panel-Button-Down"
       = "Interface\\Buttons\\UI-Panel-Button-Highlight"
       = {}
       = "Interface\\AddOns\\NickAlert\\Green-Panel-Button-Up.tga"
       = "Interface\\AddOns\\NickAlert\\Green-Panel-Button-Down.tga"
       = "Interface\\AddOns\\NickAlert\\Green-Panel-Button-Highlight.tga"
                if self.displayedColor == self.color then
                self.displayedColor = self.color
                if ( self:IsEnabled() ) then
                if ( self:IsEnabled() ) then
                if ( self:IsEnabled() ) then
        <ButtonText name="$parentText"/>
        <NormalFont style="GameFontNormal"/>
        <HighlightFont style="GameFontHighlight"/>
        <HighlightTexture inherits="UIPanelButtonHighlightTexture"/>

Phanx 01-14-13 11:04 PM

That's actually quite inefficient, for several reasons:

(1) You're using an OnUpdate script -- which runs every time a video frame is drawn, 25-100 or more times per second, depending on your system -- to check for something (the current skin) that changes rarely, or never, during any given session since most users do not sit around repeatedly changing the same option. OnUpdate scripts are very expensive in CPU terms, and should only be used for timers, animations, and other things that can't be done any other way.

(2) You're creating a bunch of extra tables -- which cost memory -- for every button created. Also, you're creating your tables in the least efficient way possible, with tons of extra table lookups. Instead of doing:


t = {}
t.alpha = 1
t.beta = 2
t.gamma = {} = 42 = 84

just construct the table directly:

t = {
        alpha = 1,
        beta = 2,
        gamma = {
                foo = 42,
                bar = 84,

This has the incidental advantage of being easier to read, too.

(3) You're doing a bunch of table lookups on every mousedown/mouseup event, even though the result of any given lookup will almost always be the same.

Instead of doing all this, you should either:

(a) use the default template, and use the technique outlined in my previous post to change the textures when needed, or

(b) use a custom template that starts out one color, and change the textures "by hand" instead of changing the "" value and letting an expensive OnUpdate function check if it should change the textures 25-100 times per second.

Also, if you're not already using XML to define your frames -- and you shouldn't, unless you really really love XML, or you are writing secure templates for action buttons/unit frames/state drivers/etc. -- you don't need to use XML for this either. Rather than defining a template and inheriting it, just use a "factory" function to generate your frames:


local ButtonTextures = {
        RED = {
                up = "Interface\\Buttons\\UI-Panel-Button-Up",
                down = "Interface\\Buttons\\UI-Panel-Button-Down",
                highlight = "Interface\\Buttons\\UI-Panel-Button-Highlight",
        GREEN = {
                up = "Interface\\AddOns\\NickAlert\\Green-Panel-Button-Up",
                down = "Interface\\AddOns\\NickAlert\\Green-Panel-Button-Down",
                highlight = "Interface\\AddOns\\NickAlert\\Green-Panel-Button-Highlight",

local function GetSkin(self)
        return self.__skin

local function SetSkin(self, skin)
        if self.__skin == skin then return end
        self.__skin = skin

        if self:IsMouseOver() and IsMouseButtonDown() then
                local down = ButtonTextures[skin].down
                local up = ButtonTextures[skin].up

        self:SetHighlightTexture(ButtonTextures[skin].highlight, "ADD")
        self:GetHighlightTexture():SetTexCoord(0, 80/128, 0, 22/32)

local function OnMouseDown(self, button)
        local down = ButtonTextures[self.__skin].down

local function OnMouseUp(self, button)
        local up = ButtonTextures[self.__skin].up

local function NewButton(parent, skin, name)
        local button = CreateFrame("Button", name, parent or UIParent)
        button:SetSize(40, 22)

        local left = button:CreateTexture(nil, "BACKGROUND")
        left:SetTexCoord(0, 12/128, 0, 22/32)
        button.Left = left

        local right = button:CreateTexture(nil, "BACKGROUND")
        right:SetTexCoord(68/128, 80/128, 0, 22/32)
        button.Right = right

        local middle = button:CreateTexture(nil, "BACKGROUND")
        middle:SetPoint("TOPLEFT", left, "TOPRIGHT")
        middle:SetPoint("BOTTOMRIGHT", right, "BOTTOMLEFT")
        middle:SetTexCoord(12/128, 68/128, 0, 22/32)
        button.Middle = middle

        local text = button:CreateFontString(nil, "OVERLAY", "GameFontNormal")

        button:SetScript("OnMouseDown", OnMouseDown)
        button:SetScript("OnMouseUp", OnMouseUp)
        button:SetScript("OnShow", OnMouseUp)

        button.GetSkin = GetSkin
        button.SetSkin = SetSkin

        SetSkin(button, skin or "RED")

        return button

This (a) reuses tables and functions instead of creating duplicate copies for every new button, (b) does not require anything to be in the global namespace, unless you choose to give the button a global name, in which case it only adds one global per button, (c) minimizes table lookups, and (d) avoids the use of an expensive OnUpdate script. It also doesn't require any XML.

Then, instead of:
local button = CreateFrame("Button", nil, SomeFrame, "UIPanelButtonTemplate") = "GREEN"
local button = NewButton(parent, "GREEN")
When you want to change the skin, instead of doing = "RED" do button:SetSkin("RED").

If you want to check which skin the button is using, do button:GetSkin().

Billtopia 01-15-13 02:00 PM

Thanks... I did the xml like that because I didn't know what I could access from lua outside the xml... never messed with it so I wasn't sure what the scope for everything would be. I prefer lua as it isn't as extremely verbose and I am used to using it. As for the OnUpdate bit, not knowing the scope of things from the xml, that was the only way I could think to be sure I could directly interact with it. That is why I didn't even use a timer to delay the loops as I thought that an equity check would be less of an impact than incrementing a value, then checking it. One operation instead of 2... I have not done much in the ways of GUIs in my addons... just some small frames and what not (except for control panel pages)

so, how bad was the xml since I never used it before anyways?

All times are GMT -6. The time now is 03:59 AM.

vBulletin © 2018, Jelsoft Enterprises Ltd
© 2004 - 2017 MMOUI