Quantcast WoWInterface - View Single Post - SecureHandlerAttributeTemplate optimization
View Single Post
03-16-19, 10:48 AM   #1
Terenna
A Warpwood Thunder Caller
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 99
SecureHandlerAttributeTemplate optimization

Good afternoon,

I along with other users have noticed a recent change with BFA where certain quests utilize an attribute change on action buttons to show them. The best example of this is during the quest Righteous Retribution: https://www.wowhead.com/quest=49741/...ution#comments

After mounting the gryphon Galeheart, you enter an Overridebar state. However, you initially don't have any buttons. The buttons are later added via an attribute change. Addons such as rActionBar, and I'm sure others, do not account for this, and assume the buttons will be there during their '_onstate-page' secure snippets. As such, I first came up with a solution to simply hooksecureframe a function that ran just as this occurred. While this code:
Lua Code:
  1. hooksecurefunc('ActionBarController_UpdateAll', function()  
  2.     for i = 1, 12 do
  3.         local button = _G['ActionButton'..i]
  4.         local overrideButton = _G['OverrideActionBarButton'..i]
  5.         local _, spellID
  6.         if overrideButton then
  7.             _, spellID = GetActionInfo(overrideButton.action)
  8.         end
  9.  
  10.         if ((HasOverrideActionBar() or HasVehicleActionBar()) and (spellID and spellID > 0)) or (not HasOverrideActionBar() and not HasVehicleActionBar()) then
  11.             button:SetAttribute('statehidden', false)
  12.             button:Show()
  13.         else
  14.             button:SetAttribute('statehidden', true)
  15.             button:Hide()
  16.         end
  17.     end
  18. end)

works wonderfully, it causes taint, as I'm changing the attributes of buttons outside of a secureframe.

As such, and not knowing much about SecureHandler*Template coding, I embarked on this endeavor. I came up with the following code:
Lua Code:
  1. local AttributeChangedFrame = CreateFrame('frame', nil, UIParent, 'SecureHandlerAttributeTemplate')
  2. for i = 1, 12 do
  3.     local button = _G['ActionButton'..i]
  4.     AttributeChangedFrame:SetFrameRef('ActionButton'..i, button)
  5. end
  6.  
  7. for i = 1, 6 do
  8.     local overrideButton = _G['OverrideActionBarButton'..i]
  9.     AttributeChangedFrame:SetFrameRef('OverrideActionBarButton'..i, overrideButton)
  10. end
  11. AttributeChangedFrame:Execute([[
  12.     buttons = table.new()
  13.     for i = 1, 12 do
  14.         table.insert(buttons, self:GetFrameRef('ActionButton'..i))
  15.     end
  16.     overridebuttons = table.new()
  17.     for i = 1, 6 do
  18.         table.insert(overridebuttons, self:GetFrameRef('OverrideActionBarButton'..i))
  19.     end
  20. ]])
  21.  
  22. for i = 1, 6 do
  23.     local overrideButton = _G['OverrideActionBarButton'..i]
  24.     overrideButton:HookScript('OnAttributeChanged', function()
  25.         AttributeChangedFrame:Execute[[
  26.             for i = 1, 6 do
  27.                 if not overridebuttons[i]:GetAttribute('statehidden') then
  28.                     buttons[i]:SetAttribute('statehidden', false)
  29.                     buttons[i]:Show()
  30.                 else
  31.                     buttons[i]:SetAttribute('statehidden', true)
  32.                     buttons[i]:Hide()
  33.                 end
  34.             end
  35.         ]]
  36.     end)
  37.    
  38.     local button = _G['ActionButton'..i]
  39.     button:HookScript('OnAttributeChanged', function()
  40.         AttributeChangedFrame:Execute[[
  41.             for i = 1, 6 do
  42.                 if (not HasOverrideActionBar() and not HasVehicleActionBar() and buttons[i]:GetAttribute('statehidden')) then
  43.                     buttons[i]:SetAttribute('statehidden', false)
  44.                     buttons[i]:Show()
  45.                 end
  46.             end
  47.         ]]
  48.     end)
  49. end

The basic idea is to hook into the OnAttributeChanged functions for both the normal actionbar button (ActionButton1-12) and the OverrideActionBarButton1-6. Here, I would execute secure code to change the attributes of the buttons to properly display the actionbutton when you "page" into an actionbar but the buttons come later. Just looking at this code, I feel like it is not great. I'm sure it can be better optimized, but I wanted to reach out to people who perhaps have better experience with SecureHandlers to determine my next steps.

Any feedback is greatly appreciated. Please note, the bottom code functions precisely how I'd like it to. It is taint free, and handles every scenario I can think of without fail. All I'm asking is for optimization so it doesn't run 36 times instead of 6 for example.
  Reply With Quote