WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Little help fixing too flashy garrison frames (https://www.wowinterface.com/forums/showthread.php?t=50867)

AnrDaemon 12-25-14 03:14 PM

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?

Dridzt 12-25-14 04:38 PM

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.

AnrDaemon 12-25-14 04:56 PM

That's an idea. Thankfully I've the necessary infrastructure already in place.

AnrDaemon 12-25-14 08:23 PM

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.

semlar 12-25-14 10:44 PM

Just add "##Dependencies: Blizzard_GarrisonUI" to the toc file, unless your addon needs to do something before the garrison addon loads.

AnrDaemon 12-25-14 11:14 PM

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. :rolleyes:

SDPhantom 12-25-14 11:40 PM

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.

AnrDaemon 12-25-14 11:47 PM

Yeah, that could be a solution, too. If I would to write a separate addon :)
Which I probably would, considering other factors.

semlar 12-25-14 11:56 PM

Quote:

Originally Posted by AnrDaemon (Post 303252)
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. :rolleyes:

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.

SDPhantom 12-26-14 12:08 AM

Quote:

Originally Posted by semlar (Post 303256)
Quote:

Originally Posted by AnrDaemon (Post 303252)
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. :rolleyes:

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.

AnrDaemon 12-26-14 08:46 AM

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?

AnrDaemon 12-26-14 10:25 PM

Quote:

Originally Posted by SDPhantom (Post 303254)
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.

Phanx 12-26-14 11:23 PM

Quote:

Originally Posted by AnrDaemon (Post 303270)
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?

AnrDaemon 12-27-14 08:20 AM

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.

Phanx 12-28-14 02:14 AM

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.

AnrDaemon 12-28-14 10:53 AM

Thank you very much for your examples! Have a happy new year!

AnrDaemon 01-18-15 06:04 PM

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.)

Phanx 01-19-15 06:14 AM

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.

AnrDaemon 01-19-15 06:43 AM

Quote:

Originally Posted by Phanx (Post 305268)
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.

Phanx 01-19-15 09:41 AM

Quote:

Originally Posted by AnrDaemon (Post 305270)
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


All times are GMT -6. The time now is 04:38 PM.

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