Quantcast 2.x Secure State Headers - WoWInterface
Thread Tools Display Modes
08-25-08, 01:06 PM   #1
BDelacroix
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 33
2.x Secure State Headers

I have been beating my head against this brick wall for a week now.

I'm working on trying to get this mod to work and then I'll try to understand the 3.0 changes.

I am down to just guessing now and that's getting nowhere very quickly.

Yes, I'm told that this will be easier with 3.x. I don't see that as being comforting since I can't find much about it beyond Iriel's documentation. Perhaps I'm just an idiot, but I don't think so.

So, what is the obvious thing I've done in the below code?

I'll tell you what it does do. I get the button I create. I can right and left click in the parent frame to change the state. That piece of code isn't in the box below. What does not happen is, at no time does a spell ever get cast. The button just presses and animates. No error message. No attempt to cast the spell I thought I associated with any of the virtual buttons.

The spell names are spelled right as I can change this up to a normal secure button without states and it casts nicely. I just can't change what the button does in combat.

All the examples I've seen only use secureactionbarbutton. That has functionality I don't want. Namely its tied to action buttons. Perhaps changing spells per state is not allowed.

Code:
	ntraps=trapper:enumeratetraps()
	if ntraps then
-- Create buttons for each trap
			trap_b = CreateFrame("Button","trapper_button",trapper,"ActionButtonTemplate,SecureActionButtonTemplate")

-- set state spell attributes &
-- build statebutton string

			statestring="1:S1"
			for t = 1, ntraps do
				if t>1 then
					statestring=statestring..";"..t..":S"..t
				end
			end
			trap_b:SetAttribute("statebutton",statestring)

-- Set possible states
			trap_b:SetAttribute("newstate","1-"..ntraps..":=")
			
-- Set type and spell for each state
			for t = 1, ntraps do
				trap_b:SetAttribute("type1-S"..t,"spell")
				trap_b:SetAttribute("spell-S"..t,trap_n[t])
			end

-- add this button as a child of the state header
			trapper:SetAttribute("addchild",trab_b)

-- set the state to "1"
			trap_b:SetAttribute("state","1")

			trap_b:SetScript("OnAttributeChanged", TrapButton_Update)

-- Set the image for the button
			trap_b:SetNormalTexture(trap_i[1])
			trap_b:SetPushedTexture(trap_i[1])
  Reply With Quote
08-25-08, 01:35 PM   #2
Foxlit
A Warpwood Thunder Caller
 
Foxlit's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 91
Code:
trap_b:SetAttribute("type1-S"..t,"spell")
should be
Code:
trap_b:SetAttribute("type-S"..t,"spell")
---

On getting to grips with secure state headers
There are two main interesting parts that you should look at when things are not working out:
  • FrameXML/SecureTemplates.lua , which defines convenience getter methods and SecureActionButton_OnClick, which actually does protected actions when you click on a SecureActionButton.
  • FrameXML/SecureStateHeader.lua , which implements the entire state header framework. The crucial trick is that SecureStateHeader wraps the OnClick handler of buttons added to it through the "addchild" attribute, making SecureStateChild_OnClick execute before, and call SecureActionButton_OnClick.

Read the SecureButton_GetModifiedAttribute, SecureState_GetStateAttribute, SecureState_GetStateModifiedAttribute functions - they're important to figure out which attributes are valid in which case.
__________________
... and you do get used to it, after a while.

Last edited by Foxlit : 08-25-08 at 02:04 PM.
  Reply With Quote
08-25-08, 01:46 PM   #3
Foxlit
A Warpwood Thunder Caller
 
Foxlit's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 91
For a more complete change-spell-on-state example:

Code:
 local sBtn = CreateFrame("Button", nil, UIParent, "SecureActionButtonTemplate"); -- [1]
 parentHeader:SetAttribute("addchild", sBtn); -- [2]
 sBtn:SetAttribute("statebutton", "1:state1;2:state2;3:state3"); -- [3]

 local spells = {"Immolation Trap", "Frost Trap", "Snake Trap"};
 sBtn:SetAttribute("type", "spell"); -- [4]
 for i=1,#spells do
  sBtn:SetAttribute("*spell-state"..i, spells[i]); -- [5]
 end
  1. Create a SecureActionButton to do things with. There's no skin included here -- you'd need to add your own textures, dimensions and anchors to actually see the action button.
  2. parentHeader is the SecureStateHeader whose state this button will alter behavior based on. Setting the "addchild" attribute on a SecureStateHeader fires its SecureStateHeader_OnAttributeChanged, which applies the necessary changes to the child -- like replacing the child's OnClick handler with SecureStateChild_OnClick.
  3. This attribute makes SecureStateChild_OnClick change the button attribute passed to SecureActionButton_OnClick (the default OnClick handler for a SecureActionButton) based on the header's state. In this case, if the header is in state 1, the SAB thinks the button "state1" was used to click it; same with "state2" in state 2 and "state3" in state 3. The attribute's general syntax is "state:newbuttonstring;otherstatetherbuttonstring;...".
  4. All three actions are spells, so we do not have to bother with modifying the "type" attribute based on anything.
  5. Both "type" and "spell" attributes are retrieved using SecureButton_GetModifiedAttribute. So, in this attribute's name ("*spell-state{i}", where {i} is replaced by numbers 1 to 3 depending on the iteration of the for loop):
    • "*" prefix enables all modifier combinations.
    • "spell" is the actual unmodified attribute name.
    • "-state{i}" is the button this attribute is valid for. The state1, state2, state3 buttons are the result of the "statebutton" attribute set above.
__________________
... and you do get used to it, after a while.

Last edited by Foxlit : 08-25-08 at 01:59 PM.
  Reply With Quote
08-25-08, 02:35 PM   #4
BDelacroix
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 33
Thank you for your responses.

There has to be something subtle I'm just missing on this because even when I change things around to your example, the button still never casts a spell.

I'm out of time today, I'll look at it again tomorrow.

Again, thank you.
  Reply With Quote
08-26-08, 12:23 PM   #5
BDelacroix
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 33
Ok, Its a new day....

Since I couldn't get the spells to actually work on states, I went with a different approach. I also needed to change the icon depending on state and I couldn't find a way to do that in combat.

I went with a different approach using "hidestate"/"showstate".

In this scheme I create up to 5 buttons and put them all in the same space. All but one is hidden per state.

That works. Except then I found out that whenever I click the button it changes the state automatically to the next one in line. I'd rather that didn't happen except by some other method. For testing that is clicking in the bordering frame.

Now, I can make the state change up and down. I do the math myself and all. I have stopped the secureheader from moving the state on the button with every click with:

SetAttribute("newstate","1-5:=")

I read that notation somewhere, it works.

I change the state programatically with SetAttribute("state",x)

that changes the state BUT introduces a new problem I've not been able to work around. It doesn't seem to actually update all the buttons.

In my research I tried ActionButton_Update(). This is no good because my button isn't actually an action bar button. It therefore bashes out when trying to use a function ActionGetTexture(action) internally.

Again, I don't want to make it an action button as that defeats the purpose of what I'm doing with this.

I seem to be so close with this. In fact, if I can find a way to update the secureheader and its children I'd be good to go.

Now I am torturing myself looking through the securexxxxtemplate.lua codes to see how those are updated.
  Reply With Quote
08-26-08, 02:18 PM   #6
Iriel
Super Moderator
WoWInterface Super Mod
Featured
Join Date: Jun 2005
Posts: 578
You can put your own code in the on state changed method on the header, then run whatever you need in there (It obviously can't do secure stuff, but it sounds like you're just trying to update visuals)
  Reply With Quote
08-27-08, 06:01 AM   #7
BDelacroix
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 33
Unfortunately, I want the buttons to update their own hide/show status which is a secure thing. So basically, I want them to update themselves according to the rules I set up in all the secureheader junk.

I'll keep looking, but its a real mess.

The real fun is, I get to do this all again when 3.0 comes out. But I have to stay busy for now rather than just wait around and learn that from scratch.
  Reply With Quote
08-28-08, 06:34 AM   #8
BDelacroix
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 33
I forgot to bring my keyfob thing with me yesterday so I couldn't do any testing. Today, however, I could.

I am now convinced I just cannot do what I want to do. I did manage to get the secureheader frame and all its children to update whenever I forced a state change.

Unfortunately,

" Interface action failed because of an AddOn "

Bla effin bla

It seems wrong, though since I see target windows hide and show all the time during combat. Oh well.

I guess my only choice is the five-buttons-on-the-screen option. Works great out of combat, right where you don't care.
  Reply With Quote
08-28-08, 07:58 AM   #9
BDelacroix
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 33
I also tried a different approach. Never figured out why the statebutton didn't work before but it does now.

So, with this approach I create 1 button made into a child of the stateheader frame.

Each state is tied to a different trap.

I do not want the state to change when clicked, instead I want it to change with another event (eventually a mousewheel but for now its a click in the state frame rather than the button)

Ok, well. It works out of combat just fine.

In combat, apparently, I'm not allowed to update the button state.
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » 2.x Secure State Headers

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