Thread Tools Display Modes
12-25-14, 03:14 PM   #1
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
Little help fixing too flashy garrison frames

I'm trying to make a permanent fix to abusive garrison interface.
I've found a way to disable flash for order queue frame, …
lua Code:
  1. frame = GarrisonCapacitiveDisplayFrame.FinishedGlow
  2. frame:SetScript("OnShow", frame.Hide)
  3. frame:Hide()
…but it only works, if I've seen that frame at least once in current game session.
How can I go about it firing automatically at the right moment?

Last edited by AnrDaemon : 12-25-14 at 03:30 PM.
  Reply With Quote
12-25-14, 04:38 PM   #2
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,360
Garrison UI is probably a LoD Blizzard addon.

You should register ADDON_LOADED and watch for arg1 being "Blizzard_GarrisonUI", then do whatever to the frame.
  Reply With Quote
12-25-14, 04:56 PM   #3
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
That's an idea. Thankfully I've the necessary infrastructure already in place.
  Reply With Quote
12-25-14, 08:23 PM   #4
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
On a second thought, I could use a little hint or two.
Right now, I have everything in a single file. Which, quite unsurprisingly, grow "a little" unwieldy.
I plan to separate stuff into more manageable chunks. However, the order of execution is important.

Right now, the code is laid like this:

Main addon frame (listener) is created right away, along with events table.
Then some additional stuff happens, that is not relevant to anything at this point.
Then events table is populated by callback functions, one per event. Like,
Code:
function events:PLAYER_ENTERING_WORLD(...) … end
…and all the things are written inside.
Then the callbacks are registered as listeners. Like the usual
lua Code:
  1. for eventName, eventFunc in pairs(events) do
  2.   -- Register all events for which handlers have been defined
  3.   frame:RegisterEvent(eventName)
  4. end

The problem as I see it is I can no longer registed events right away in the main block. I need to postpone them. May be I should hook some event that is fired very early first, and do the registration there? Which event, if that is a good idea?

P.S.
I plan to use
Code:
local addonName, addon = ...
and pass the data structures inside the "local-global" "addon" table, so that is not an issue.
  Reply With Quote
12-25-14, 10:44 PM   #5
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
Just add "##Dependencies: Blizzard_GarrisonUI" to the toc file, unless your addon needs to do something before the garrison addon loads.
  Reply With Quote
12-25-14, 11:14 PM   #6
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
That would cause Garrison UI to load unconditionally, wouldn't it?
I'd like to avoid it, if I can help it. My loading times already quite long.
Besides, I can use some coding practice.
  Reply With Quote
12-25-14, 11:40 PM   #7
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,326
If you use this instead, it would tag your addon as LoD and load with the Blizzard addon.
Code:
## LoadOnDemand: 1
## LoadWith: Blizzard_GarrisonUI
I don't remember if LoadWith automatically tags as LoD if the target is LoD too, but it doesn't hurt to define it as one manually.

Edit: LoadWith does automatically set your addon as LoD and it requires the target to be LoD as well.
__________________
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 : 12-25-14 at 11:52 PM.
  Reply With Quote
12-25-14, 11:47 PM   #8
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
Yeah, that could be a solution, too. If I would to write a separate addon
Which I probably would, considering other factors.
  Reply With Quote
12-25-14, 11:56 PM   #9
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
Originally Posted by AnrDaemon View Post
That would cause Garrison UI to load unconditionally, wouldn't it?
I'd like to avoid it, if I can help it. My loading times already quite long.
Besides, I can use some coding practice.
No, adding an addon as a dependency tells the game to load your addon after the dependency is loaded.

It doesn't force the dependency to load.
  Reply With Quote
12-26-14, 12:08 AM   #10
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,326
Originally Posted by semlar View Post
Originally Posted by AnrDaemon View Post
That would cause Garrison UI to load unconditionally, wouldn't it?
I'd like to avoid it, if I can help it. My loading times already quite long.
Besides, I can use some coding practice.
No, adding an addon as a dependency tells the game to load your addon after the dependency is loaded.

It doesn't force the dependency to load.
Actually, his assumption was correct. In my test, I modified the ToC of my TrainAll addon to use the Dependencies tag instead of LoadWith. Immediately before the addon loaded as part of the startup process, it loaded the dependency.

What Dependencies does is modify the load order so the target loads before your addon. If the addon isn't found, yours will not be loaded. OptionalDeps has the same behavior with the exception that it will allow your addon to load without the target if it doesn't exist. If the target is LoD and your addon isn't, the target will be loaded at startup.

LoadWith was created to allow an addon to load immediately after a target LoD addon loads.



Edit: If Dependencies is used with LoadOnDemand flagged, your addon will never load unless called by LoadAddOn(). Forcing your addon to load at such time will also force the target LoD addon to load too. However, your addon will not load with the target as the OP had wanted. This is what LoadWith is for.
__________________
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 : 12-26-14 at 12:28 AM.
  Reply With Quote
12-26-14, 08:46 AM   #11
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
Going back to events and order of execution. (Not related to Garrison UI now, but just because we've touched that already.)
Is there any documentation on the order of events firing? Or a library that may help managing accumulation and registration of event callbacks?
  Reply With Quote
12-26-14, 10:25 PM   #12
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
Originally Posted by SDPhantom View Post
If you use this instead, it would tag your addon as LoD and load with the Blizzard addon.
Code:
## LoadOnDemand: 1
## LoadWith: Blizzard_GarrisonUI
I don't remember if LoadWith automatically tags as LoD if the target is LoD too, but it doesn't hurt to define it as one manually.

Edit: LoadWith does automatically set your addon as LoD and it requires the target to be LoD as well.
Actually, LoadWith does NOT set my addon as LoD. Without LoD=1 the scheme just did not work at all.
However, with
Code:
## LoadWith: Blizzard_GarrisonUI
## LoadOnDemand: 1
everything fell in place. I'm one frame happier now, than I was before.
  Reply With Quote
12-26-14, 11:23 PM   #13
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by AnrDaemon View Post
Is there any documentation on the order of events firing? Or a library that may help managing accumulation and registration of event callbacks?
Registering for events is very simple and straightforward; you don't need a library to do it. If you're handling just a few events, just do an if/elseif chain in your frame's OnEvent script. If you're handling lots of events, you may want to factor out each event's handler into its own function:

Code:
local MyAddon = CreateFrame("Frame")
MyAddon:SetScript("OnEvent", function(self, event, ...) return self[event](self, ...) end)
MyAddon:RegisterEvent("SOME_EVENT_HERE")

function MyAddon:SOME_EVENT_HERE(some_arg, some_other_arg)
    -- Do stuff here
end
As for the order of events, there really isn't one, outside of the initial loading process. Events indicate that things have happened in the game, and there's no fixed order for what happens in the game -- you can gain a buff, enter combat or cast a spell at any time, and so can the players around you, etc.

Was there some specific aspect of event handling you're having trouble with?
__________________
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
12-27-14, 08:20 AM   #14
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
There was, but it seems it was lost in the beginning of the thread
I'lll reiterate.
I have an addon that grew a little to big to manage it in one function. But it IS, basically, a few functions - event listeners.
I want to split it into several files. But I would like to retain core functionality in one file.
Passing the data around seems to be a nonissue through global addon table.
But registration of events, I can't do it in one file straight away (create fame, register events, then write handlers in separate files? - I just don't know, what these handlers will be).
Now, that I'm writing it, I've got an idea.
What if I add a metatable to my events table? And every time a key is added or removed, I would registed the main frame for listening on that event, or remove listeners, if table is empty? Seems like a very simple idea. Perhaps, there is already a library to manage such kind of things? Although, I'll probably try to write one myself, just for practice. Never used metatables before.
  Reply With Quote
12-28-14, 02:14 AM   #15
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
I use this in my personal "do a bunch of random stuff" mod:
Code:
local _, addon = ...

local f = CreateFrame("Frame")
f:SetScript("OnEvent", function(self, event, ...)
	for func, handler in pairs(self[event]) do
		if handler then
			func(handler, ...)
		else
			func(...)
		end
	end
end)

function addon:RegisterEvent(event, func, handler)
	if handler then
		func = handler[func]
	end
	if func then
		f[event] = f[event] or {}
		f[event][func] = handler or false
		f:RegisterEvent(event)
	end
end

function addon:UnregisterEvent(event, func, handler)
	if handler then
		func = handler[func]
	end
	if func and f[event] and f[event][func] ~= nil then
		f[event][func] = nil
		if not next(f[event]) then
			f[event] = nil
			f:UnregisterEvent(event)
		end
	end
end
Then you can do any of these:
Code:
addon:RegisterEvent("UNIT_HEALTH", function(unit)
    -- do stuff
end)
Code:
local function healthFunc(unit)
    -- do stuff
end
addon:RegisterEvent("UNIT_HEALTH", healthFunc)
addon:UnregisterEvent("UNIT_HEALTH", healthFunc)
Code:
function addon:UpdateHealth(unit)
    -- do stuff
end
addon:RegisterEvent("UNIT_HEALTH", "UpdateHealth", addon)
addon:UnregisterEvent("UNIT_HEALTH", "UpdateHealth", addon)
Code:
local healthFrame = CreateFrame("Frame", "MyHealthFrame", UIParent)
function healthFrame:Update(unit)
   -- do stuff
end
addon:RegisterEvent("UNIT_HEALTH", "Update", healthFrame)
addon:UnregisterEvent("UNIT_HEALTH", "Update", healthFrame)
It does not support RegisterUnitEvent, so if you need to listen for a high-frequency event like UNIT_POWER_FREQUENT on just one unit, you're still better off creating a dedicated frame and using RegisterUnitEvent.

Other options would be to use AceEvent-3.0 with or without AceAddon-3.0, or to just create a separate event handler frame in each file.
__________________
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 : 01-19-15 at 09:41 AM.
  Reply With Quote
12-28-14, 10:53 AM   #16
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
Thank you very much for your examples! Have a happy new year!
  Reply With Quote
01-18-15, 06:04 PM   #17
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
Correct me, if I wrong, but this one:
Lua Code:
  1. function addon:UnregisterEvent(event, func, handler)
  2.     if handler then
  3.         func = handler[func]
  4.     end
  5.     if func and f[event] and f[event][func] then
  6.         f[event][func] = nil
  7.         if not next(f[event]) then
  8.             f[event] = nil
  9.             f:UnregisterEvent(event)
  10.         end
  11.     end
  12. end
…will fail on "f[event][func] = handler = false". (I.e. a callback being a simple function, not an object method.)
  Reply With Quote
01-19-15, 06:14 AM   #18
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
No. If there's no "handler" then it's assumed that the "func" is a function. You could add some type checks but there's not really any point -- it's not a shared library, so your mistakes won't break other addons.

If you meant the "next" part, the answer is also no -- "next" returns two values, with the first being a key, the second the value of that key. The code in question there only cares about the first value -- the key -- which can only be a function.
__________________
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
01-19-15, 06:43 AM   #19
AnrDaemon
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 156
Originally Posted by Phanx View Post
No. If there's no "handler" then it's assumed that the "func" is a function.
When the "func" is a function, you set "handler" to "false" in event registration.
When you check for f[event][func], it'll return your "false" and unregister will not succeed.

Last edited by AnrDaemon : 01-19-15 at 07:50 AM.
  Reply With Quote
01-19-15, 09:41 AM   #20
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by AnrDaemon View Post
When you check for f[event][func], it'll return your "false" and unregister will not succeed.
Oh, you're right, I wasn't looking at that part. That line should probably be changed to:

Code:
		if func and f[event] and f[event][func] ~= nil then
__________________
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

WoWInterface » Developer Discussions » Lua/XML Help » Little help fixing too flashy garrison frames


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