Thread Tools Display Modes
07-29-18, 09:40 PM   #1
Theroxis
A Fallenroot Satyr
Join Date: Jun 2018
Posts: 24
Hooking a data provider mixin?

So this seems like an oversight by blizzard with frame naming conventions...
I'm trying to change the zone text font size when mousing over a zone in BattlefieldMapFrame, this text, it's frame and it's size are all handled by this code:
https://github.com/tomrus88/Blizzard...taProvider.lua

Since this code never declares any logical frame names, the frames have a randomly generated ID for their name. This is:
A) Undesirable
B) Difficult to manipulate.


How should I approach hooking a function here to call self:SetFont()?

This is foreign territory to me because the data providers are kind of supposed to be hands off, but seeing as this is the only place this frame is accesible reliably this is the approach that must be taken...
  Reply With Quote
07-30-18, 01:26 AM   #2
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
GetRegion()
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)
  Reply With Quote
07-30-18, 11:12 PM   #3
Theroxis
A Fallenroot Satyr
Join Date: Jun 2018
Posts: 24
Originally Posted by zork View Post
GetRegion()
I'll have to play with this some more, so far I've only gotten Select(#, BattlefieldMapFrame.ScrollContainer:GetRegion()):SetFont(...) to throw errors, no matter which number is passed to it. I might be approaching it wrong though. I've also tried the same with .Name:SetFont() It's a tad weird as technically this is something of a different class altogether a "label" and has a restricted set of functions. Using WorldMapTextFont:SetFont() works, but also changes the font on the WorldMapFrame; which is undesirable.

Thanks for pointing me in a correct direction, trying to hooksecurefunc a data provider seems like asking for trouble in a lot of different ways. I'm certain that either GetChild or GetRegion can grab the correct element reliably, just gotta figure out the correct arguments.
  Reply With Quote
07-31-18, 06:45 AM   #4
kurapica.igas
A Chromatic Dragonspawn
Join Date: Aug 2011
Posts: 152
Lua Code:
  1. for k, v in pairs(BattlefieldMapFrame.dataProviders) do
  2.     if k.Label then
  3.         local ft = { k.Label.Name:GetFont() }
  4.         k.Label.Name:SetFont(ft[1], ft[2] * 0.5, ft[3])
  5.        
  6.         local ft = { k.Label.Description:GetFont() }
  7.         k.Label.Description:SetFont(ft[1], ft[2] * 0.5, ft[3])
  8.     end
  9. end

I may add a scale modifier in the EFBM addon in next version. Since they are created in the EBFM.
  Reply With Quote
07-31-18, 11:47 AM   #5
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
Originally Posted by kurapica.igas View Post
Lua Code:
  1. for k, v in pairs(BattlefieldMapFrame.dataProviders) do
  2.     if k.Label then
  3.         local ft = { k.Label.Name:GetFont() }
  4.         k.Label.Name:SetFont(ft[1], ft[2] * 0.5, ft[3])
  5.        
  6.         local ft = { k.Label.Description:GetFont() }
  7.         k.Label.Description:SetFont(ft[1], ft[2] * 0.5, ft[3])
  8.     end
  9. end

I may add a scale modifier in the EFBM addon in next version. Since they are created in the EBFM.
Almost, you'll want to make sure that the Label is indeed the AreaLabel one, as more providers have a .Label member.
Also, that is a very wasteful use of tables.

Slightly improved:
Lua Code:
  1. for k, v in pairs(BattlefieldMapFrame.dataProviders) do
  2.     if k.Label and k.setAreaLabelCallback then
  3.         local font, size, flags = k.Label.Name:GetFont()
  4.         k.Label.Name:SetFont(font, size * 0.5, flags)
  5.  
  6.         local font, size, flags = k.Label.Description:GetFont()
  7.         k.Label.Description:SetFont(font, size * 0.5, flags)
  8.     end
  9. end

As a sidenote, there are discussions on how to improve hooking into the providers of a canvas-based map frame, and one of the suggested solutions is being able to query by mixin name. Feel free to chime in with alternate suggestions.

Last edited by p3lim : 07-31-18 at 11:49 AM.
  Reply With Quote
07-31-18, 12:35 PM   #6
MunkDev
A Scalebane Royal Guard
 
MunkDev's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2015
Posts: 431
Not sure if relevant, but you can hook a specific function in a mixin to find the object that calls the inherited function. There's a slight caveat, in that hooking will only apply to objects that didn't exist when your addon loaded.
Lua Code:
  1. hooksecurefunc(MapCanvasMixin, 'AcquirePin', AcquirePin)
__________________
  Reply With Quote
07-31-18, 09:19 PM   #7
kurapica.igas
A Chromatic Dragonspawn
Join Date: Aug 2011
Posts: 152
Originally Posted by p3lim View Post
Almost, you'll want to make sure that the Label is indeed the AreaLabel one, as more providers have a .Label member.
For now, there is only one data provider with Label field. Never mind, Theroxis is talking about my addon EnhanceBattlefieldMinimap, the area label is created in it, so in the newest version, a setting is already given for the labels.

Back to the hooking data provider, since there is no action button on the world map, it's safe to just replaced them with our own codes, I replaced some of them to reduce the memory increment, like :
Lua Code:
  1. local viewRect  = CreateRectangle(0, 0, 0, 0)
  2.  
  3. BattlefieldMapFrame.ScrollContainer.CalculateViewRect =  function (self, scale)
  4.     local childWidth, childHeight = self.Child:GetSize()
  5.     local left = self:GetHorizontalScroll() / childWidth
  6.     local right = left + (self:GetWidth() / scale) / childWidth
  7.     local top = self:GetVerticalScroll() / childHeight
  8.     local bottom = top + (self:GetHeight() / scale) / childHeight
  9.  
  10.     viewRect:SetSides(left, right, top, bottom)
  11.  
  12.     return viewRect  -- the origin: CreateRectangle(left, right, top, bottom)
  13. end

Unfortunately, waste comes from the APIS can't be done.

If we need use the hooksecurefunc, the target should be the object created from the CreateFromMinxin, like(The Label has a Mixin named AreaLabelFrameMixin) :
Lua Code:
  1. local areaLabelDataProvider = CreateFromMixins(AreaLabelDataProviderMixin)
  2. BattlefieldMapFrame:AddDataProvider(areaLabelDataProvider)
  3. hooksecurefunc(areaLabelDataProvider.Label, "SetLabel", print)
  Reply With Quote
07-31-18, 10:29 PM   #8
Theroxis
A Fallenroot Satyr
Join Date: Jun 2018
Posts: 24
Originally Posted by kurapica.igas View Post
For now, there is only one data provider with Label field. Never mind, Theroxis is talking about my addon EnhanceBattlefieldMinimap, the area label is created in it, so in the newest version, a setting is already given for the labels.

Back to the hooking data provider, since there is no action button on the world map, it's safe to just replaced them with our own codes, I replaced some of them to reduce the memory increment, like :
Lua Code:
  1. local viewRect  = CreateRectangle(0, 0, 0, 0)
  2.  
  3. BattlefieldMapFrame.ScrollContainer.CalculateViewRect =  function (self, scale)
  4.     local childWidth, childHeight = self.Child:GetSize()
  5.     local left = self:GetHorizontalScroll() / childWidth
  6.     local right = left + (self:GetWidth() / scale) / childWidth
  7.     local top = self:GetVerticalScroll() / childHeight
  8.     local bottom = top + (self:GetHeight() / scale) / childHeight
  9.  
  10.     viewRect:SetSides(left, right, top, bottom)
  11.  
  12.     return viewRect  -- the origin: CreateRectangle(left, right, top, bottom)
  13. end

Unfortunately, waste comes from the APIS can't be done.

If we need use the hooksecurefunc, the target should be the object created from the CreateFromMinxin, like(The Label has a Mixin named AreaLabelFrameMixin) :
Lua Code:
  1. local areaLabelDataProvider = CreateFromMixins(AreaLabelDataProviderMixin)
  2. BattlefieldMapFrame:AddDataProvider(areaLabelDataProvider)
  3. hooksecurefunc(areaLabelDataProvider.Label, "SetLabel", print)

Learning from/with you while tweaking and improving your addon is fantastic. Thanks for being so responsive! Hopefully I can get to a point where I'm helping more than just having you add features! LOL


Originally Posted by p3lim View Post
As a sidenote, there are discussions on how to improve hooking into the providers of a canvas-based map frame, and one of the suggested solutions is being able to query by mixin name. Feel free to chime in with alternate suggestions.
Personally (from other development in languages not as foreign to myself as lua) I typically expect things that behave like the dataproviders do to put things into categorically appropriate arrays (tables, for lua, I guess?) for ease of integration.
Using this case as an example, instead of the DataProvider completely omitting the name field, it should create a new child variable of the parent frame:

*MapFrame.AreaLabelMixin

And then that should provide child elements for different properties; in this case:
*MapFrame.AreaLabelMixin.Label[#]

This avoids the case of having random ID's floating around in memory and relying on costly iterative conditional logic.
Basically following Object Oriented Philosphy, any time a function adds variables into the memory map it should behave like a class does, and expose those variables appropriately so they can be addressed in a human manner. It prevents confusing situations down the road, too. Obviously this would have to be implemented by Blizzard, and in some cases may not be appropriate - the pins for various nodes for example. Maybe have the parent table have names and then have the children have random ID's since that data is more or less going to be random regardless.

Last edited by Theroxis : 07-31-18 at 10:37 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Hooking a data provider mixin?

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