Thread Tools Display Modes
03-26-14, 08:39 PM   #1
Duugu
Premium Member
 
Duugu's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 851
Spellflyout, SpellFlyout_Toggle, and taint

Hello all

I'm stuck with a bad problem again.


My intention is to use Blizzards spellflyout feature, and to modify the layout of the flyout itself if the flyout buttons are shown (means: the expanding list of spells).

My first approach was this:

Lua Code:
  1. SecureHandler_OnLoad(_G["SpellFlyoutButton1"])
  2. _G["SpellFlyoutButton1"]:WrapScript(_G["SpellFlyoutButton1"], "OnShow", [[
  3.     local flyoutButtonSize = 29
  4.     local rangeFromAButton = 5
  5.     local t = string.sub(self:GetName(), 18)
  6.     local degrees = self:GetParent():GetParent():GetAttribute("degree") * 3.14159265 / 180
  7.     local nx = math.cos(degrees) - (((flyoutButtonSize * t) + rangeFromAButton) * math.sin(degrees))
  8.     local ny = math.sin(degrees) + (((flyoutButtonSize * t) + rangeFromAButton) * math.cos(degrees))
  9.     if self then
  10.         self:ClearAllPoints()
  11.         self:SetPoint("CENTER", self:GetParent():GetParent(), "CENTER", nx, ny)
  12.     end
  13. ]])

SpellFlyoutButton1 is the first of the expanding flyout buttons, and the solution works very well for the first button. The buttons new position is exactly as expected.

But ... there's a problem with the next buttons (a flyout can have a lot of buttons as you know). If the UI loads then only the first of the buttons (SpellFlyoutButton1) is created. All other buttons are created 'on the fly' if they are really needed.

Here's a part of the code for this from the Blizz interface file SpellFlyout.lua ("Createframe" at the bottom):

Lua Code:
  1. function SpellFlyout_Toggle(self, flyoutID, parent, direction, distance, isActionBar, specID, showFullTooltip)
  2.     if (self:IsShown() and self:GetParent() == parent) then
  3.         self:Hide();
  4.         return;
  5.     end
  6.  
  7.     local offSpec = specID and (specID ~= 0);
  8.    
  9.     -- Save previous parent to update at the end
  10.     local oldParent = self:GetParent();
  11.     local oldIsActionBar = self.isActionBar;
  12.  
  13.     local _, _, numSlots, isKnown = GetFlyoutInfo(flyoutID);
  14.     local actionBar = parent:GetParent();
  15.     self:SetParent(parent);
  16.     self.isActionBar = isActionBar;
  17.  
  18.     -- Make sure this flyout is known or we are showing an offSpec flyout
  19.     if ((not isKnown and not offSpec) or numSlots == 0) then
  20.         self:Hide();
  21.         return;
  22.     end
  23.    
  24.     if (not direction) then
  25.         direction = "UP";
  26.     end
  27.    
  28.     -- Update all spell buttons for this flyout
  29.     local prevButton = nil;
  30.     local numButtons = 0;
  31.     for i=1, numSlots do
  32.         local spellID, overrideSpellID, isKnown, spellName, slotSpecID = GetFlyoutSlotInfo(flyoutID, i);
  33.         local visible = true;
  34.        
  35.         -- Ignore Call Pet spells if there isn't a pet in that slot
  36.         local petIndex, petName = GetCallPetSpellInfo(spellID);
  37.         if (isActionBar and petIndex and (not petName or petName == "")) then
  38.             visible = false;
  39.         end
  40.        
  41.         if ( ((not offSpec or slotSpecID == 0) and visible and isKnown) or (offSpec and slotSpecID == specID) ) then
  42.             local button = _G["SpellFlyoutButton"..numButtons+1];
  43.             if (not button) then
  44.                 button = CreateFrame("CHECKBUTTON", "SpellFlyoutButton"..numButtons+1, SpellFlyout, "SpellFlyoutButtonTemplate");
  45.             end

Now the problem: Obviously I can't set up my WrapScript before the button exists. So I have to listen if the player clicks on a flyout button for the first time (for example via hooking "SpellFlyout_Toggle" - see above) and to apply my script then. Unfortunately this could happen if the player is in combat. And if I then set the WrapScript everything is tainted. :/

The only possible way to work around this I can think of is to force the creation of all flyout buttons before the player enters combat.
My first approach to do this was calling SpellFlyout_Toggle() with a set of suitable arguments to initiate the frame creation. Which worked fine. I've managed it to call the function, the flyout was visible, I've wrapped my script to all of the flyout buttons and everything was great.
Until I entered combat and tried to open the flyout button ... then the interface stated my code was tainted (when executing the wrapped script). :/

That means, if I call SpellFlyout_Toggle() manually from unsecure code, and if the flyout frames are created by SpellFlyout_Toggle() then they are unsecure!? I'm not sure if I do understand why.

The second point is: how do I force the flyout button frames to get build from secure code (like inside a secure snippet) if I can't use SpellFlyout_Toggle() or reference the "Spellflyout" frame there?

I'm a bit lost to be honest. Any thoughts or words that could help to enlighten me are greatly appreciated. Thank you.
  Reply With Quote
03-26-14, 09:30 PM   #2
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
You should modify them as they are created. Don't force them to be created.
__________________
"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
03-26-14, 09:31 PM   #3
Duugu
Premium Member
 
Duugu's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 851
Originally Posted by Seerah View Post
You should modify them as they are created. Don't force them to be created.
But if I wait for them to be created it could be in combat. And if I apply the wrapscript in combat the frame is tainted. :/

[e]
Nevermind. Thanks for your reply.

I guess it's less time consuming to build my own flyout feature than trying to use the existing one.

Last edited by Duugu : 03-26-14 at 09:44 PM.
  Reply With Quote
03-27-14, 09:12 AM   #4
Duugu
Premium Member
 
Duugu's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 851
The bad thing is, my own flyout would mean I have to call GetFlyoutInfo(). Which means the flyout spells could be dragged to the button out of combat only. :/

The secure framework is such a mess.
  Reply With Quote
03-27-14, 01:13 PM   #5
ravagernl
Proceritate Corporis
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,176
Couldn't you store a reference to a secure frame inside an array in combat, and after combat, loop through that same array, do stuff and wipe it after that?
  Reply With Quote
03-27-14, 02:19 PM   #6
Duugu
Premium Member
 
Duugu's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 851
Hm.

To implement my own flyout functionality I'll have to query and store the spells/spellids that a flyout (like the mage 'Portal') provides in when the player drags the flyout to my action button.

If the player then actually opens the flyout I'll have to set those spellids to all the pop out flyout buttons.

The only way to get the actual spellids of a flyout is GetFlyoutInfo()/GetFlyoutSlotInfo(). Which is unsecure and can't be directly called insided a secure snippet. I could call it via CallMethod() and unsecure code. But this will cause taint if I do this in combat.

So as far as I understand the whole thing is, that it is impossible to get the actual spell ids of a flyout in combat without tainting my frames.

Am I wrong?


[e]
I could pre-build a simple list of all flyout spells that are available to get around GetFlyoutInfo. Not smart but at least working.
Does anyone have an idea where to get a list of all available flyout spells?

[e2] Doh. Ok. New idea: I'll query all flyoutIDs up to ... whatever ... 1k and query and store all slots for flyoutIDs that exist on addon load. Then I'll pre-setup flyout action buttons for all of them on addon load. And in combat, if a player drags a flyout to an action button, I'll just have to move/show them. Don't know if this could work, but I'll try it tonight.
Also not smart, but could work.

Last edited by Duugu : 03-27-14 at 02:52 PM.
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » Spellflyout, SpellFlyout_Toggle, and taint


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