Thread Tools Display Modes
08-19-15, 11:32 AM   #1
evilbib
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jun 2010
Posts: 30
Question about hooks

Hi,

lets assume I have this setup:
AddOn1\file1.lua
Lua Code:
  1. local addon, ns = ...
  2. local function DoSomething()
  3.     local frame = CreateFrame("Frame")
  4. end

AddOn2\file2.lua
Lua Code:
  1. --ready to hook the function DoSomething() from file1.lua

So is it possible to access the created "frame" in file2.lua?
  Reply With Quote
08-19-15, 11:48 AM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Well, I'm not sure "hooks" are actually what you're asking about, and you certainly shouldn't create a function in one file in your addon and hook it in another. Hooks are for when you want to modify something in Blizzard code or another addon. If you're writing your own code, just write it the way you want it in the first place.

That said, to share something between files in your addon, just add it to your addon's private table; you've named it "ns" in your code:

AddOn1\file1.lua
Lua Code:
  1. local addon, ns = ...
  2. local frame = CreateFrame("Frame")
  3. ns.frame = frame

AddOn2\file2.lua
Lua Code:
  1. local addon, ns = ...
  2. local frame = ns.frame
__________________
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
08-19-15, 12:36 PM   #3
evilbib
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jun 2010
Posts: 30
Originally Posted by Phanx View Post
Hooks are for when you want to modify something in Blizzard code or another addon.
Thats exactly what I want to do, modify something from another addon (not mine).
AddOn1/file1.lua is all what this addon provides.
  Reply With Quote
08-19-15, 12:39 PM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Well, then this is where posting fake code examples gets you in trouble... if the actual code is set up like your example (local "frame" with no name, parent, or distinguishing features created inside a local function) then no, there's no way to access it from another file in another addon. However, it seems unlikely that a real addon would actually do that, so there's probably a way... but without seeing the actual code, there's no way to tell.
__________________
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
08-19-15, 02:17 PM   #5
evilbib
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jun 2010
Posts: 30
Originally Posted by Phanx View Post
Well, then this is where posting fake code examples gets you in trouble... if the actual code is set up like your example (local "frame" with no name, parent, or distinguishing features created inside a local function) then no, there's no way to access it from another file in another addon. However, it seems unlikely that a real addon would actually do that, so there's probably a way... but without seeing the actual code, there's no way to tell.
Actually the addon (teksLoot) returns this frame, this is the whole function:
Lua Code:
  1. local function CreateRollFrame()
  2.     local frame = CreateFrame("Frame", nil, UIParent)
  3.     frame:SetWidth(328)
  4.     frame:SetHeight(26)
  5.     frame:SetBackdrop(backdrop)
  6.     frame:SetBackdropColor(0, 0, 0, .9)
  7.     frame:SetScript("OnEvent", OnEvent)
  8.     frame:RegisterEvent("CANCEL_LOOT_ROLL")
  9.     frame:CreateBeautyBorder(11)
  10.     frame:SetBeautyBorderPadding(-1)
  11.     frame:Hide()
  12.  
  13.     local button = CreateFrame("Button", nil, frame)
  14.     button:SetPoint("LEFT", 0, 0)
  15.     button:SetWidth(28)
  16.     button:SetHeight(28)
  17.     --button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
  18.     button:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
  19.     button:GetHighlightTexture():SetBlendMode("ADD")
  20.     button:SetScript("OnEnter", SetItemTip)
  21.     button:SetScript("OnLeave", HideTip2)
  22.     button:SetScript("OnUpdate", ItemOnUpdate)
  23.     button:SetScript("OnClick", LootClick)
  24.     frame.button = button
  25.  
  26.     local buttonborder = CreateFrame("Frame", nil, button)
  27.     buttonborder:SetWidth(32)
  28.     buttonborder:SetHeight(32)
  29.     buttonborder:SetPoint("CENTER", button, "CENTER")
  30.     buttonborder:SetBackdrop(backdrop)
  31.     buttonborder:SetBackdropColor(1, 1, 1, 0)
  32.     buttonborder:CreateBeautyBorder(11)
  33.     buttonborder:SetBeautyBorderPadding(-1)
  34.     frame.buttonborder = buttonborder
  35.  
  36.     local tfade = frame:CreateTexture(nil, "BORDER")
  37.     tfade:SetPoint("TOPLEFT", frame, "TOPLEFT", 4, -4)
  38.     tfade:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -4, 4)
  39.     tfade:SetTexture("Interface\\ChatFrame\\ChatFrameBackground")
  40.     tfade:SetBlendMode("ADD")
  41.     tfade:SetGradientAlpha("VERTICAL", .1, .1, .1, 0, .25, .25, .25, 1)
  42.  
  43.     local status = CreateFrame("StatusBar", nil, frame)
  44.     status:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -4, -4)
  45.     status:SetPoint("BOTTOM", frame, "BOTTOM", 0, 4)
  46.     status:SetPoint("LEFT", frame.button, "RIGHT", -1, 0)
  47.     status:SetScript("OnUpdate", StatusUpdate)
  48.     status:SetFrameLevel(status:GetFrameLevel()-1)
  49.     status:SetStatusBarTexture("Interface\\AddOns\\teksLoot\\media\\statusbar.tga")
  50.     status:SetStatusBarColor(.8, .8, .8, .9)
  51.     status.parent = frame
  52.     frame.status = status
  53.  
  54.     local spark = frame:CreateTexture(nil, "OVERLAY")
  55.     spark:SetWidth(14)
  56.     spark:SetHeight(35)
  57.     spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
  58.     spark:SetBlendMode("ADD")
  59.     status.spark = spark
  60.  
  61.     local need, needtext = CreateRollButton(frame, "Interface\\Buttons\\UI-GroupLoot-Dice-Up", "Interface\\Buttons\\UI-GroupLoot-Dice-Highlight", "Interface\\Buttons\\UI-GroupLoot-Dice-Down", 1, NEED, "LEFT", frame.button, "RIGHT", 5, -1)
  62.     local greed, greedtext = CreateRollButton(frame, "Interface\\Buttons\\UI-GroupLoot-Coin-Up", "Interface\\Buttons\\UI-GroupLoot-Coin-Highlight", "Interface\\Buttons\\UI-GroupLoot-Coin-Down", 2, GREED, "LEFT", need, "RIGHT", 0, -1)
  63.     local de, detext
  64.     de, detext = CreateRollButton(frame, "Interface\\Buttons\\UI-GroupLoot-DE-Up", "Interface\\Buttons\\UI-GroupLoot-DE-Highlight", "Interface\\Buttons\\UI-GroupLoot-DE-Down", 3, ROLL_DISENCHANT, "LEFT", greed, "RIGHT", 0, -1)
  65.     local pass, passtext = CreateRollButton(frame, "Interface\\Buttons\\UI-GroupLoot-Pass-Up", nil, "Interface\\Buttons\\UI-GroupLoot-Pass-Down", 0, PASS, "LEFT", de or greed, "RIGHT", 0, 2.2)
  66.     frame.needbutt, frame.greedbutt, frame.disenchantbutt = need, greed, de
  67.     frame.need, frame.greed, frame.pass, frame.disenchant = needtext, greedtext, passtext, detext
  68.  
  69.     local bind = frame:CreateFontString()
  70.     bind:SetPoint("LEFT", pass, "RIGHT", 3, 1)
  71.     bind:SetFont("Fonts\\FRIZQT__.TTF", 13, "OUTLINE")
  72.     frame.fsbind = bind
  73.  
  74.     local loot = frame:CreateFontString(nil, "ARTWORK", "SystemFont_Outline")
  75.     loot:SetPoint("LEFT", bind, "RIGHT", 0, .12)
  76.     loot:SetPoint("RIGHT", frame, "RIGHT", -5, 0)
  77.     loot:SetHeight(16)
  78.     loot:SetJustifyH("LEFT")
  79.     frame.fsloot = loot
  80.  
  81.     frame.rolls = {}
  82.  
  83.     return frame
  84. end
  Reply With Quote
08-19-15, 02:41 PM   #6
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
Because the function that creates the frame is local, only code within that .lua file can call CreateRollFrame().

Becasue the frame is not given a name, there is no way for code outside that .lua file to access the frame once it has been created unless the fames is parented to another frame that at some stage has been given a name.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 08-19-15 at 02:44 PM.
  Reply With Quote
08-19-15, 04:20 PM   #7
Banknorris
A Chromatic Dragonspawn
 
Banknorris's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2014
Posts: 153
If that frame has some distinctive features you might be able to use EnumerateFrames() to get a pointer to it. For example this code catches all existent action buttons (from standard UI, Bartender4, ButtonForge, Dominos etc) and new ones will be added as well. Doesn't matter if they have a name or parent. (code extracted and adapted from SetMacroIcon lib)

Lua Code:
  1. local action_buttons = {} --this table will contain all action buttons (present and future)
  2.  
  3. local hook_all_actionbuttons
  4. local CreateFrame_hook
  5.  
  6. local hook_new_buttons_frame = CreateFrame("Frame")
  7. hook_new_buttons_frame:Hide()
  8.  
  9. local f = CreateFrame("Frame")
  10. f:SetScript("OnEvent",function(self,event,...)
  11.     if event=="PLAYER_LOGIN" then
  12.         hook_all_actionbuttons()
  13.         hooksecurefunc("CreateFrame",CreateFrame_hook)
  14.     end
  15. end)
  16. f:RegisterEvent("PLAYER_LOGIN")
  17.            
  18. function CreateFrame_hook(frame_type,frame_name,frame_parent,frame_template)
  19.     --put code to identify viable candidates for the desired frame here (like bellow)
  20.     if string_upper(frame_type)=="CHECKBUTTON" and frame_template and string_upper(frame_template):match("ACTIONBUTTONTEMPLATE") then
  21.         hook_new_buttons_frame:Show()
  22.     end
  23. end
  24.  
  25. do
  26. local last_frame
  27. function hook_all_actionbuttons()
  28.     local frame = EnumerateFrames(last_frame)
  29.     while frame do
  30.         --put code to identify the desired frame here (like bellow)
  31.         local frame_type = frame:GetObjectType()
  32.         if frame_type=="CheckButton" and frame.GetAttribute and frame.icon and frame.Border and frame.Count then
  33.             action_buttons[frame] = true
  34.         end
  35.         last_frame = frame
  36.         frame = EnumerateFrames(frame)
  37.     end
  38. end
  39. end
  40.  
  41. hook_new_buttons_frame:SetScript("OnUpdate",function(self,elapsed)
  42.     self:Hide()
  43.     hook_all_actionbuttons()
  44. end)
__________________
"In this world nothing can be said to be certain, except that fractional reserve banking is a Ponzi scheme and that you won't believe it." - Mandrill

Last edited by Banknorris : 08-19-15 at 04:46 PM.
  Reply With Quote
08-19-15, 04:48 PM   #8
elcius
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Sep 2011
Posts: 75
there is no clean way to access a local anonymous frame.
Code:
local hooked = {};

-- run on START_LOOT_ROLL
local frames = {GetFramesRegisteredForEvent('CANCEL_LOOT_ROLL')};
for i,frame in pairs(frames) do
	if (not hooked[frame]) and frame.status and frame.status:GetStatusBarTexture():match('teksLoot') then
		-- hook frame, or just apply changes here once.
		hooked[frame] = true;
	end
end
  Reply With Quote
08-19-15, 04:54 PM   #9
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
Scanning EnumerateFrames() can be very taxing on the system considering the default UI alone creates hundreds of frames. Trying to "hack" your way to get access to a local frame is customized to that specific frame. One way I can think of that would be much easier on the system is to use GetFramesRegisteredForEvent("CANCEL_LOOT_ROLL") and cross-check the taint record of any existing index.

Lua Code:
  1. local function GetTeksRollFrame()
  2.     local list={GetFramesRegisteredForEvent("CANCEL_LOOT_ROLL")};
  3.     for i,j in ipairs(list) do
  4.         if j.button and select(2,issecurevariable(j,"button"))=="teksLoot" then
  5.             return j;
  6.         end
  7.     end
  8. end

Hacking these frames isn't always going to be easy and it takes a lot of understanding with the environment they exist in. Not only the function creating a frame, but every function that takes the frame in as an argument is a possible point of entry to capture it. Scanning methods like the ones posted here are a last resort if you can't find a viable point of entry to get direct access.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 08-19-15 at 04:56 PM.
  Reply With Quote
08-20-15, 05:39 PM   #10
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by pingumania View Post
Actually the addon (teksLoot) ...
In that specific case you're probably better off just modifying the addon directly. It's so small and infrequently updated -- in fact, the last change was made in 2012 -- that porting your changes between versions is trivial. I actually maintain a script that applies small patches to a number of addons after updating, so I don't have to do it by hand.
__________________
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
08-21-15, 02:44 AM   #11
evilbib
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jun 2010
Posts: 30
Originally Posted by Phanx View Post
In that specific case you're probably better off just modifying the addon directly. It's so small and infrequently updated -- in fact, the last change was made in 2012 -- that porting your changes between versions is trivial. I actually maintain a script that applies small patches to a number of addons after updating, so I don't have to do it by hand.
Thats what I did in the end
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Question about hooks

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