Thread Tools Display Modes
01-10-13, 10:13 AM   #1
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
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...
  Reply With Quote
01-10-13, 04:31 PM   #2
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
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)
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
01-10-13, 04:40 PM   #3
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
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
  Reply With Quote
01-12-13, 08:40 PM   #4
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
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...
  Reply With Quote
01-12-13, 08:41 PM   #5
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
frame:GetNormalTexture():SetTexCoord(a,b,c,d)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
01-12-13, 08:43 PM   #6
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
sweet... you are a WoW Lua GOD and I kneel at your feet
  Reply With Quote
01-13-13, 09:52 AM   #7
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
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 Click image for larger version

Name:	redbutton.jpg
Views:	365
Size:	3.2 KB
ID:	7501

my green button Click image for larger version

Name:	greenbutton.jpg
Views:	411
Size:	4.4 KB
ID:	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)
  Reply With Quote
01-13-13, 05:53 PM   #8
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
01-13-13, 06:56 PM   #9
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
I only want the button green some of the time... like to indicate when that option is enabled
  Reply With Quote
01-13-13, 11:13 PM   #10
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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.

See:
http://wow.go-hero.net/framexml/1644...mplates.xml#18

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).
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
01-14-13, 07:36 AM   #11
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
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
  Reply With Quote
01-14-13, 07:17 PM   #12
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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:
Code:
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
highlight:SetAllPoints(true)
highlight:SetTexture(path)
It would also be far less flexible than just slicing up the texture yourself.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
01-14-13, 08:29 PM   #13
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
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

Code:
<?xml version="1.0" encoding="utf-8"?>
<Ui xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.blizzard.com/wow/ui/" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
    <Button name="RedGreenButtonTemplate" virtual="true">
        <Size x="40" y="22"/>
        <Layers>
            <Layer level="BACKGROUND">
                <Texture parentKey="Left" file="Interface\Buttons\UI-Panel-Button-Up">
                    <Size x="12" y="22"/>
                    <Anchors>
                        <Anchor point="TOPLEFT"/>
                        <Anchor point="BOTTOMLEFT"/>
                    </Anchors>
                    <TexCoords left="0" right="0.09375" top="0" bottom="0.6875"/>
                </Texture>
                <Texture parentKey="Right" file="Interface\Buttons\UI-Panel-Button-Up">
                    <Size x="12" y="22"/>
                    <Anchors>
                        <Anchor point="TOPRIGHT"/>
                        <Anchor point="BOTTOMRIGHT"/>
                    </Anchors>
                    <TexCoords left="0.53125" right="0.625" top="0" bottom="0.6875"/>
                </Texture>
                <Texture parentKey="Middle" file="Interface\Buttons\UI-Panel-Button-Up">
                    <Size x="12" y="22"/>
                    <Anchors>
                        <Anchor point="TOPLEFT" relativeKey="$parent.Left" relativePoint="TOPRIGHT"/>
                        <Anchor point="BOTTOMRIGHT" relativeKey="$parent.Right" relativePoint="BOTTOMLEFT"/>
                    </Anchors>
                    <TexCoords left="0.09375" right="0.53125" top="0" bottom="0.6875"/>
                </Texture>
            </Layer>
        </Layers>
        <Scripts>
            <OnLoad>
                self.displayedColor = "red"
                self.color = "red"
                self.skins = {}
                self.skins.red = {}
                self.skins.red.up = "Interface\\Buttons\\UI-Panel-Button-Up"
                self.skins.red.down = "Interface\\Buttons\\UI-Panel-Button-Down"
                self.skins.red.highlight = "Interface\\Buttons\\UI-Panel-Button-Highlight"
                
                self.skins.green = {}
                self.skins.green.up = "Interface\\AddOns\\NickAlert\\Green-Panel-Button-Up.tga"
                self.skins.green.down = "Interface\\AddOns\\NickAlert\\Green-Panel-Button-Down.tga"
                self.skins.green.highlight = "Interface\\AddOns\\NickAlert\\Green-Panel-Button-Highlight.tga"
                
            </OnLoad>
            <OnUpdate>
                if self.displayedColor == self.color then
                    return
                end
                self.displayedColor = self.color
                self.Left:SetTexture(self.skins[self.displayedColor].up);
                self.Middle:SetTexture(self.skins[self.displayedColor].up);
                self.Right:SetTexture(self.skins[self.displayedColor].up);
                self:SetHighlightTexture(self.skins[self.displayedColor].highlight);
            </OnUpdate>
            <OnMouseDown>
                if ( self:IsEnabled() ) then
                    self.Left:SetTexture(self.skins[self.displayedColor].down);
                    self.Middle:SetTexture(self.skins[self.displayedColor].down);
                    self.Right:SetTexture(self.skins[self.displayedColor].down);
                end
            </OnMouseDown>
            <OnMouseUp>
                if ( self:IsEnabled() ) then
                    self.Left:SetTexture(self.skins[self.displayedColor].up);
                    self.Middle:SetTexture(self.skins[self.displayedColor].up);
                    self.Right:SetTexture(self.skins[self.displayedColor].up);
                end
            </OnMouseUp>
            <OnShow>
                if ( self:IsEnabled() ) then
                    self.Left:SetTexture(self.skins[self.displayedColor].up);
                    self.Middle:SetTexture(self.skins[self.displayedColor].up);
                    self.Right:SetTexture(self.skins[self.displayedColor].up);
                    self:SetHighlightTexture(self.skins[self.displayedColor].highlight)
                end
            </OnShow>
        </Scripts>
        <ButtonText name="$parentText"/>
        <NormalFont style="GameFontNormal"/>
        <HighlightFont style="GameFontHighlight"/>
        <HighlightTexture inherits="UIPanelButtonHighlightTexture"/>
    </Button>
</Ui>
  Reply With Quote
01-14-13, 11:04 PM   #14
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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:

Code:
t = {}
t.alpha = 1
t.beta = 2
t.gamma = {}
t.gamma.foo = 42
t.gamma.bar = 84
just construct the table directly:
Code:
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 "self.skin" 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:

Code:
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
end

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
		self.Left:SetTexture(down)
		self.Right:SetTexture(down)
		self.Middle:SetTexture(down)
	else
		local up = ButtonTextures[skin].up
		self.Left:SetTexture(up)
		self.Right:SetTexture(up)
		self.Middle:SetTexture(up)
	end

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

local function OnMouseDown(self, button)
	local down = ButtonTextures[self.__skin].down
	self.Left:SetTexture(down)
	self.Right:SetTexture(down)
	self.Middle:SetTexture(down)
end

local function OnMouseUp(self, button)
	local up = ButtonTextures[self.__skin].up
	self.Left:SetTexture(up)
	self.Right:SetTexture(up)
	self.Middle:SetTexture(up)
end

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:SetPoint("TOPLEFT")
	left:SetPoint("BOTTOMLEFT")
	left:SetWidth(12)
	left:SetTexCoord(0, 12/128, 0, 22/32)
	button.Left = left

	local right = button:CreateTexture(nil, "BACKGROUND")
	right:SetPoint("TOPRIGHT")
	right:SetPoint("BOTTOMRIGHT")
	right:SetWidth(12)
	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")
	text:SetAllPoints(true)
	text:SetJustifyH("CENTER")
	text:SetJustifyV("CENTER")
	button:SetFontString(text)
	button:SetNormalFontObject("GameFontNormal")
	button:SetHighlightFontObject("GameFontHighlight")	

	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
end
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")
button.skin = "GREEN"
do:
local button = NewButton(parent, "GREEN")
When you want to change the skin, instead of doing button.skin = "RED" do button:SetSkin("RED").

If you want to check which skin the button is using, do button:GetSkin().
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
01-15-13, 02:00 PM   #15
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
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?
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Coloring standard buttons

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off