WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   AlertFrame identified by numbers? (https://www.wowinterface.com/forums/showthread.php?t=58435)

LudiusMaximus 12-04-20 06:40 PM

AlertFrame identified by numbers?
 
I want to set the UIFrame alpha to 0 but still see the alert frames (e.g. from achievements or world quests). So I guess what I have to do is run SetIgnoreParentAlpha(true) on the respective frames. But what frames are these? When I use /fstack I get some strange names consisting of numbers. How could I handle this?


SDPhantom 12-05-20 11:14 AM

Frames that don't have a name or weren't created with the ParentKey XML attribute will have a random number in /fstack. This is basically their internal memory pointer similar to if you tostring() a table or function. There isn't a practical way to reference a frame with this number. It's mainly to show something's there and differentiate it from any other unnamed frame.

These are very likely created using frame pools and you'll need to look at the source code to find a way to get to them.

LudiusMaximus 12-05-20 12:53 PM

All right, thanks! I was afraid so... :-)

I already looked in the Blizzard code and found AlertFrameSystems.lua to be most promising.
It includes this function:
Code:

function WorldQuestCompleteAlertFrame_SetUp(frame, questData)
  PlaySound(SOUNDKIT.UI_WORLDQUEST_COMPLETE);

  frame.questID = questData.questID;
  frame.QuestName:SetText(questData.taskName);

  frame.QuestTexture:SetTexture(questData.icon);

  frame.ToastText:SetText(questData.displayAsObjective and TOAST_OBJECTIVE_COMPLETE or WORLD_QUEST_COMPLETE);

  ResetRewardFrames(frame);

  if questData.money > 0 then
    local rewardFrame = GetRewardFrame(frame, "WorldQuestFrameRewardTemplate");
    DungeonCompletionAlertFrameReward_SetRewardMoney(rewardFrame, questData.money);
  end

  if questData.xp > 0 and not IsPlayerAtEffectiveMaxLevel() then
    local rewardFrame = GetRewardFrame(frame, "WorldQuestFrameRewardTemplate");
    DungeonCompletionAlertFrameReward_SetRewardXP(rewardFrame, questData.xp);
  end

  if questData.currencyRewards then
    for currencyIndex, currencyTexture in ipairs(questData.currencyRewards) do
      local rewardFrame = GetRewardFrame(frame, "WorldQuestFrameRewardTemplate");
      SetPortraitToTexture(rewardFrame.texture, currencyTexture);
      rewardFrame.currencyIndex = currencyIndex;
    end
  end

  StandardRewardAlertFrame_AdjustRewardAnchors(frame);
end


So I tried to hook it:
Code:

hooksecurefunc("WorldQuestCompleteAlertFrame_SetUp", function(...)
  print("WorldQuestCompleteAlertFrame_SetUp", ...)
end)


But I never see the print of my hook...

Am I missing something?

Vrul 12-05-20 04:04 PM

Quote:

Originally Posted by LudiusMaximus (Post 337798)
But I never see the print of my hook...

Am I missing something?

That function runs before your code ever has a chance to hook it.

You need something like:
Lua Code:
  1. local function SetIgnoreParentAlpha(_, frame)
  2.     frame:SetIgnoreParentAlpha(true)
  3. end
  4.  
  5. for _, subSystem in pairs(AlertFrame.alertFrameSubSystems) do
  6.     local pool = type(subSystem) == 'table' and subSystem.alertFramePool
  7.     if type(pool) == 'table' and type(pool.resetterFunc) == 'function' then
  8.         hooksecurefunc(pool, "resetterFunc", SetIgnoreParentAlpha)
  9.     end
  10. end
Here is an easy way to test it:
Code:

/run UIParent:SetAlpha(0.5); NewMountAlertSystem:ShowAlert("123")

LudiusMaximus 12-05-20 05:57 PM

Wow, this is amazing!! How do you get to know stuff like this?? :-D

Could you also think of a way to SetIgnoreParentAlpha() of alert frames that are already shown; i.e. after the resetterFunc has already been fired?

Anyway, thank you so much!


UPDATE: I think I found a way.

Lua Code:
  1. local collectedAlertFrames = {}
  2. local alertFramesIgnoreParentAlpha = false
  3.  
  4. -- Function I call whenever I toggle UIParent's alpha.
  5. local function SetAlertFramesIgnoreParentAlpha(enable)
  6.   alertFramesIgnoreParentAlpha = enable
  7.   for _, v in pairs(collectedAlertFrames) do
  8.     v:SetIgnoreParentAlpha(enable)
  9.   end
  10. end
  11.  
  12. local function CollectAlertFrame(_, frame)
  13.   if not frame.IEF_collected then
  14.     tinsert(collectedAlertFrames, frame)
  15.     frame.IEF_collected = true
  16.     frame:SetIgnoreParentAlpha(alertFramesIgnoreParentAlpha)
  17.   end
  18. end
  19.  
  20. for _, subSystem in pairs(AlertFrame.alertFrameSubSystems) do
  21.   local pool = type(subSystem) == 'table' and subSystem.alertFramePool
  22.   if type(pool) == 'table' and type(pool.resetterFunc) == 'function' then
  23.     hooksecurefunc(pool, "resetterFunc", CollectAlertFrame)
  24.   end
  25. end

Vrul 12-05-20 06:45 PM

Quote:

Originally Posted by LudiusMaximus (Post 337805)
Could you also think of a way to SetIgnoreParentAlpha() of alert frames that are already shown; i.e. after the resetterFunc has already been fired?

That shouldn't be necessary since resetterFunc is called once when a new object is created or acquired from the pool and once when it is placed back in the pool (activeObjects and inactiveObjects respectively).

LudiusMaximus 12-05-20 06:48 PM

Yes, I don't want to interfere with other addons. So I only want the alerts to ignore parent UI when *my* addon fades out UIParent. But I got it to work. See my "UPDATE" in the previous post.


All times are GMT -6. The time now is 01:02 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI