WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   oUF (Otravi Unit Frames) (https://www.wowinterface.com/forums/forumdisplay.php?f=87)
-   -   Proposal - Embeddable oUF Extension Mods (https://www.wowinterface.com/forums/showthread.php?t=21152)

PProvost 03-15-09 07:36 PM

Proposal - Embeddable oUF Extension Mods
 
Lately I've been looking in to embedding oUF into my layout to make a self-contained addon. Haste supports this quite well with his metadata trick at the top of each file in oUF:

oUF.lua:
Code:

local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')



All the files in oUF\elements:

Code:

local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = _G[global]

This is a slick trick because it lets me embed haste's oUF code inside my addon, and all I have to do is put this in my addon's TOC (assuming I've put oUF in a subfolder called oUFembed):

MyAddon\MyAddon.toc:
Code:

## X-oUF: oUFembed
oUFembed/oUF.xml

There is no required relationship between the two names in used in the TOC, but I tend to keep it that way. The X-oUF metadata tag instructs the embedded oUF to publish itself into the global namespace using the provided name. That is the important bit. The second line simply brings in the embedded oUF files.

Then, at the top of my layout file, I can reference the embedded oUF like this:

MyAddon\layout.lua:
Code:

local oUF = oUFembed
oUFembed = nil

Now anywhere in my code that I reference the symbol oUF, I will get the embedded one. Perfect! I can test against a specific version of oUF and embed it within my addon.

The problem comes when I want to embed an oUF extension written by someone else. Let's use as an example oUF_Banzai by Rabbit. If I wanted to embed it into my addon, it will fail. Oh, it won't crash, but it also won't work.

Why?

Because it makes an assumption that oUF is installed as an independent addon, and that it is published on the global symbol oUF and not oUFembed as I did above.

The first non-comment line of code enforces it like this:

oUF_Banzai.lua:
Code:

if not oUF then return end
I understand why Rabbit did this, but I think with a simple change, we can make it so oUF_Banzai (or any other oUF Extension) can work standalone or embedded. And this requires no change to oUF and should let the extensions continue to work standalone OR embedded.

If the top lines in the oUF_Banzai were as follows instead of the simple check used currently, the embedded version would work:

Proposed oUF_Banzai.lua:
Code:

local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
local oUF = _G[global] or oUF
assert(oUF, 'oUF not loaded')

Here I take advantage of the scheme used by Haste already in oUF. The only issue, which haste and I have discussed but for which there is no good workaround, is one of path length. If you embed oUF too deeply in your addon, you can hit some kind of a max-path issue in the WoW runtime, and the string returned by debugstack() will not contain a full path.

So what I'd like to propose / ask is that all oUF extension authors add these four lines of code to the top of their extensions. It makes it easier to embed and causes no harm to your existing code.

Question/comments appreciated.

Slakah 03-16-09 11:52 AM

I already do this in oUF_Fader (at least I think I do).

Although I don't like your generic global name, why not use <MyAddon>oUF instead of oUFembed, as your current name could cause some conflicts at a later date.

PProvost 03-16-09 02:20 PM

Quote:

Originally Posted by Slakah (Post 120399)
I already do this in oUF_Fader (at least I think I do).

Although I don't like your generic global name, why not use <MyAddon>oUF instead of oUFembed, as your current name could cause some conflicts at a later date.

In fact I don't use that global name, I follow the pattern you describe. My point was simply that the name the addon author chooses is HIS NAME and not anyone else's.

Thanks for calling that out.

PProvost 03-16-09 02:22 PM

Quote:

Originally Posted by Slakah (Post 120399)
I already do this in oUF_Fader (at least I think I do).

Although I don't like your generic global name, why not use <MyAddon>oUF instead of oUFembed, as your current name could cause some conflicts at a later date.

Ummm... doesn't look like you do in oUF_Fader by the way:

oUF_Fader.lua Line 1:
Code:

if not oUF then return end
This makes oUF_Fader unembeddable. :(

p3lim 03-16-09 02:55 PM

All my plug-ins support embedding.

PProvost 03-16-09 03:02 PM

Quote:

Originally Posted by p3lim (Post 120417)
All my plug-ins support embedding.

Not that I can see.

In both oUF_BarFader and oUF_RuneBar you reference the global symbol oUF (bad) without any assert or check (good). In an embedded scenario the global oUF symbol probably doesn't exist unless the layout author republished it into global scope.

The part you're missing is having this at the top of the lua file:

Code:

local parent = debugstack():match[[\AddOns\(.-)\]]
local global = GetAddOnMetadata(parent, 'X-oUF')
local oUF = _G[global] or oUF
assert(oUF, 'oUF not loaded')


Slakah 03-16-09 03:18 PM

Meh I did it for my local version, I just forgot to update it :P.

Freebaser 12-11-09 12:02 PM

This should be updated to the new system.

yj589794 12-11-09 01:10 PM

Within oUF_HealComm4 I currently use the following which if safe for servers running patch 3.2.X and patch 3.3:

Code:

local oUF
local parent
if(...) then
        parent = ...
else
        parent = debugstack():match[[\AddOns\(.-)\]]
end

local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
if(...) then
        local _, ns = ...
        oUF = ns.oUF or _G[global]
else
        oUF = _G[global]
end


a version that supports only servers running patch 3.3 would be:
Code:

local parent, ns = ...
local global = GetAddOnMetadata(parent, 'X-oUF')
assert(global, 'X-oUF needs to be defined in the parent add-on.')
local oUF = ns.oUF or _G[global]


I think all current live servers run patch 3.3. It just depends on what patch the China servers will be at if they ever get running again.

haste 12-11-09 03:19 PM

Last time I talked to someone playing on China they were still on TBC, but that was around the start of November. Most of the people who care aren't playing on the Chinese servers anyway.

Anyway, just do:
Lua Code:
  1. local _, ns = ...
  2. local oUF = ns.oUF or oUF
  3.  
  4. assert(oUF, "<name> was unable to locate oUF install.")
No use support 3.2 anymore.


All times are GMT -6. The time now is 07:39 PM.

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