View Single Post
09-18-14, 09:43 PM   #5
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Lightbound View Post
Could you explain me how your day looks like? You did answer on nearly every question i got with a huge amount of informations. You got a bunch of addons running with properly a bunch of tickets each day o.o.
My work schedule is flexible, and the work itself (managing websites and doing graphic design for a local business) is not very demanding, so I do a lot of forum posting at work, and often go 24+ hours without sleeping during the week and then make up for it with 12+ hour sleep marathons on the weekend.

Originally Posted by Lightbound View Post
If i remember right you said that blizzard frames get created at the start and are always there so easy to hook. I tryed to give my skinned blizzard ui some borders but on some frames. For example .. the Guildframe. If i check it with Fstack i get nearly everywhere around it "GuildFrame" than "GuildMainFrame", "GuildNewPerksFrame", "GuildFrameInsert" and so on.
It depends on which Blizzard frames you're working with. Most of the old frames are very easy to work with. Over time Blizzard's UI programmers have started using more "advanced" tactics like delaying the creation of frames until they're actually needed, creating frames without global names, etc. In general these are good things to do, but as is sadly common, Blizzard's UI code seems to be written by people who may be excellent programmers in some other language, but are not excellent Lua programmers. Their in general is very cluttered, and in some places is just a nightmare, both to read and to interact with from addons.

For example, there's at least one place where they literally run 30+ if/elseif checks to convert a string to all-caps instead of just calling string.upper one time.

Originally Posted by Lightbound View Post
i dont know if posts on WoWInt. get flagged as "with new content" if i edit my last post.
It doesn't.

Originally Posted by Lightbound View Post
Now i need to understand the Lua. "hooksecurefunc" does as i understand it hook functions. Simple as that im not sure what is the other stuff? (Bagnon [AddOn Name], "CreateFrame" [name of the func?] function [to tell the hooksecurefunc that is has to hook a function?] (Bagnon [AddOn Name], id [no clue what it is. Maybe if there are more than 1 function with the same name]
hooksecurefunc tells WoW to run your function immediately after the original function is run; this is also called a "post hook". hooksecurefunc can also be used on secure functions, since it doesn't touch or affect the original function at all. Your function receives all the same arguments that the original function received. In this particular case, Bagnon's CreateFrame method receives two arguments -- the first is a reference to the main Bagnon object, and the second is a string identifying the frame that was created. If you were hooking a different function, then your function would receive different arguments.

There are two ways to use hooksecurefunc. For global functions:

Code:
hooksecurefunction(CastSpellByName, function(name)
     print("You cast a spell by name:", name)
end)
For functions that are defined as methods on objects:

Code:
hooksecurefunction(MinimapZoneText, "SetText", function(self, text)
     print("The minimap zone text is now showing:", text)
end)
Since the addon Bagnon creates an object (either a frame or plain table, I didn't check) with the global name "Bagnon", and a method named "CreateFrame" is defined on that object, we use the second syntax. Generally functions defined as methods are always going to receive a reference to their parent object as the first argument, eg.

Code:
function Bagnon:CreateFrame(id)
    print(self == Bagnon) -- prints "true"
end
... is functionally identical to:

Code:
function Bagnon.CreateFrame(self, id)
    print(self == Bagnon) -- prints "true"
end
There was a small discussion of this "syntactic sugar" recently here:
http://www.wowinterface.com/forums/s...573#post295573

Originally Posted by Lightbound View Post
Lua Code:
  1. if XLoot then
  2.     -- Add a border to each frame as XLoot creates it:
  3.     hooksecurefunc(XLoot, "CreateFrame", function(XLoot, id)
  4.         -- Get a reference to the frame object:
  5.         local frame = XLoot.frames[id]
  6.         -- Add your border:
  7.         frame:CreateBorder(13,20,20,20, 2)
  8.     end)
  9. end
That would only work if all of the following statements were true:

1. The XLoot addon defines a table or frame object with a global name of "XLoot".
2. The XLoot addon defines a function as a method on that object with the name of "CreateFrame".
3. That method receives two arguments, the first being a reference to the "XLoot" object, and the second being something that identifies the frame being created.
4. There is a table defined as under the "frames" key on the "XLoot" object (eg. XLoot.frames = {}).
5. The identifier passed to the XLoot:CreateFrame method is used as a key in that table, and its value is a reference to the frame that was created.

Since XLoot is a completely separate addon from Bagnon, and is not written by the same author, it's extremely unlikely that its frame creation code is exactly the same as Bagnon's frame creation code.

After a quick look at XLoot's code, I can tell you that you don't need to hook anything. XLoot only creates one loot frame (whereas Bagnon creates an inventory frame and a bank frame and possibly more frames depending on your settings) and it creates it right away when the addon loads (whereas Bagnon doesn't create any frames until you want to see them). In XLoot_Frame\Frames.lua, in the main chunk (outside of any functions, so it's executed as soon as the file is read):

Code:
local XLootFrame = CreateFrame("Frame", "XLootFrame", UIParent)
This line does the following:

1. Creates a frame object with the type "Frame" (as opposed to "Button" or "ScrollFrame" etc.)
2. Gives that object the global name "XLootFrame".
3. Parents that object to the already-existing frame with the global name "UIParent" (by reference, not by name).
4. Assigns a reference to the new object to the local variable "XLootFrame".

So, since that line is executed and the frame is created right away, all your addon needs to do is:

1. Add XLoot_Frame to its optional dependencies to make sure XLoot_Frame loads before your addon if it's installed.
2. Check if XLootFrame exists (if it doesn't at this point, then the addon isn't installed).
3. Add a border to the frame:

Code:
if XLootFrame then
     XLootFrame:AddBorder( YOUR BORDER PROPERTIES HERE)
end
If you end up adding borders to a lot of addons, you may not want to list 100 addons in your TOC's optional dependencies field, and may want to use the same strategy I use in my personal skinning/modification addon:

Code:
local addonFuncs = {}

addonFuncs["Bagnon"] = function()
     hooksecurefunc(Bagnon, "CreateFrame", function(Bagnon, id)
         -- code here, I'm too lazy to scroll down and copy/paste it
     end)
end

addonFuncs["XLoot_Frame"] = function()
     XLootFrame:AddBorder( ARGUMENTS GO HERE )
end

for addon, func in pairs(addonFuncs) do
     -- Check for addons that were already loaded before yours:
     if IsAddOnLoaded(addon) then
          -- Run the function now:
          func()
          -- Remove it from the queue:
          addonFuncs[addon] = nil
     else
          -- Check for addons that aren't installed or aren't enabled:
          local _, _, _, enabled, loadable = GetAddOnInfo(addon)
          if not enabled or not loadable then
               -- Remove it from the queue:
               addonFuncs[addon] = nil
          end
end

-- If any addons are still in the queue, listen for addon loading events:
if next(addonFuncs) then
     local eventFrame = CreateFrame("Frame")
     eventFrame:RegisterEvent("ADDON_LOADED")
     eventFrame:SetScript("OnEvent", function(self, event, addon)
          local func = addonFuncs[addon]
          if func then
               func()
               addonFuncs[addon] = nil
          end
          if not next(addonFuncs) then
               -- Clean up and send everything to the garbage collector
               self:UnregisterEvent(event)
               self:SetScript("OnEvent", nil)
               addonFuncs = nil
          end
     end)
end
__________________
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.

Last edited by Phanx : 09-19-14 at 09:51 PM.
  Reply With Quote