Thread Tools Display Modes
06/12/20, 03:49 PM   #1
QuantumPie
AddOn Author - Click to view addons
Join Date: Sep 2019
Posts: 32
Struggling to understand inherritence

I'm currently trying to develop an addon that tracks cool-downs of abilities on your bar. I have the main window made with two controls representing the front and back bar. Each of the two controls representing a bar will have 5 children containing the ability texture and a label overlapping. Instead of duplicating that layout 5 times I figured I could use inheritance but I don't quite understand how it works.

Currently my virtual control is (missing the label for now):
Lua Code:
  1. <Control name="BarTracker_Slot" virtual="true">
  2.     <Dimensions x="50" y="50"/>
  3.     <Controls>
  4.         <Texture name="$(parent)Tex">
  5.             <Anchor point="CENTER" relativePoint="CENTER"/>
  6.         </Texture>
  7.     </Controls>
  8. </Control>

And my top level is:
Lua Code:
  1. <TopLevelControl name="BarTrackerWindow">
  2.     <Controls>
  3.         <Backdrop name="$(parent)BG" alpha="1" centerColor="40000000" edgeColor="60000000" clampedToScreen="true" movable="true" mouseEnabled="true">
  4.             <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="CENTER" offsetX="0" offsetY="0"/>
  5.             <Dimensions x="250" y="100"/>
  6.             <Edge edgeSize="1"/>
  7.             <OnMouseEnter>WINDOW_MANAGER:SetMouseCursor(12);</OnMouseEnter>
  8.             <OnMouseExit>WINDOW_MANAGER:SetMouseCursor(0);</OnMouseExit>
  9.             <OnMoveStop>BarTracker.savePosition()</OnMoveStop>
  10.         </Backdrop>
  11.         <Control name="$(parent)Front">
  12.             <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeTo="$(parent)BG"/>
  13.             <Dimensions x="250" y="50"/>
  14.         </Control>
  15.         <Control name="$(parent)Back">
  16.             <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeTo="$(parent)Front"/>
  17.             <Dimensions x="250" y="50"/>
  18.         </Control>
  19. </TopLevelControl>

So how would I use the virtual in a loop to add it to the Front and Back control? I've been looking through CMX's code to try and figure it out but there is a lot and I can't figure out where they actually add the virtuals.

The other thing throwing me off is how would I reference it? The components all have their own name so the texture is "BarTracker_SlotTex". But how would I differentiate it while generating the virtual components since there will be 10 in total?
  Reply With Quote
06/12/20, 08:35 PM   #2
Dolgubon
 
Dolgubon's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2016
Posts: 408
So, there's two ways to use a template:
1. You can use it in the xml file2. You can use it in Lua code.


Note that stuff like loops is only possible in Lua code.


XML file:

With XML files, you'll need to add inherits="BarTracker_Slot". With this option, it's pretty straightforward for how the names work: exactly as the names normally work within xml. Like, whatever the control is, imagine the template info is just 'slotted' where the control is. So imagining the Front gets the BarTracker_Slot template. Then you have that control's name is the same as the name you give it (BarTrackerWindowFront) and there will be a texture under it created with name="$(parent)Tex" which will evaluate to BarTrackerWindowFrontTex.


Lua file

Within the Lua file you can use WINDOW_MANAGER:CreateControlFromVirtual(controlName, parentControl, templateToUse). So say you wanted to create a control under the BarTracker_Slot which has the template. You'd do WINDOW_MANAGER:CreateControlFromVirtual("BarTrackerWindowFrontChildNameWhateverYouWant", BarTrackerWindowFront, "BarTracker_Slot").
Then the control name is BarTrackerWindowFrontChildNameWhateverYouWant, and there's a control created under (following xml name rules) it with the name BarTrackerWindowFrontChildNameWhateverYouWantTex. Since this is in Lua code, you can use loops, ifs, etc.
  Reply With Quote
06/12/20, 08:53 PM   #3
QuantumPie
AddOn Author - Click to view addons
Join Date: Sep 2019
Posts: 32
Thanks for getting back to me! I figured that out not long ago after getting a better understanding of CMX. Unfortunately I can't get the textures to display.

The current XML I'm using is:
Lua Code:
  1. <GuiXml>
  2.     <Controls>
  3.         <Control name="BarTracker_Slot" virtual="true">
  4. <!--            <Anchor point="CENTER" relativeTo="$(parent)" relativePoint="CENTER" offsetX="0" offsetY="0"/>-->
  5.             <Controls>
  6.                 <Texture name="$(parent)Tex">
  7.                     <Anchor point="LEFT" relativePoint="LEFT"/>
  8.                     <Dimensions x="50" y="50"/>
  9.                 </Texture>
  10.             </Controls>
  11.         </Control>
  12.  
  13.         <TopLevelControl name="BarTrackerWindow">
  14.             <Dimensions x="250" y="100"/>
  15.             <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="CENTER" offsetX="0" offsetY="0"/>
  16.             <OnMouseEnter>WINDOW_MANAGER:SetMouseCursor(12);</OnMouseEnter>-->
  17.             <OnMouseExit>WINDOW_MANAGER:SetMouseCursor(0);</OnMouseExit>
  18.             <OnMoveStop>BarTracker.savePosition()</OnMoveStop>
  19.             <Controls>
  20.                 <Backdrop name="$(parent)_BG" alpha="1" centerColor="40000000" edgeColor="60000000">
  21.                     <AnchorFill />
  22.                     <Edge edgeSize="1" />
  23.                 </Backdrop>
  24.                 <Control name="$(parent)_Front">
  25.                     <Dimensions x="250" y="100" />
  26.                     <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT"/>
  27.                 </Control>
  28.                 <Control name="$(parent)_Back">
  29.                     <Dimensions x="250" y="100" />
  30.                     <Anchor point="TOPLEFT" relativeTo="$(parent)_Front" relativePoint="TOPLEFT"/>
  31.                 </Control>
  32.             </Controls>
  33.         </TopLevelControl>
  34.     </Controls>
  35. </GuiXml>

And I'm trying to use the virtual via:
Lua Code:
  1. local wm = WINDOW_MANAGER
  2.  
  3. BarTracker = {
  4.     name = "BarTracker",
  5.     author = "QuantumPie",
  6.     version = "0.0.1",
  7.     varsVersion = 1,
  8.     guiWindow = BarTrackerWindow,
  9.     guiBG = BarTrackerWindow_BG,
  10.     guiFront = BarTrackerWindow_Front,
  11.     guiBack = BarTrackerWindow_Back,
  12.     guiTemplate = "BarTracker_Slot",
  13.     wm = WINDOW_MANAGER,
  14.     defaults = {
  15.         fb = {},
  16.         bb = {},
  17.         hidden = false,
  18.         isLocked = false
  19.     }
  20. }
  21.  
  22. ...
  23.  
  24. function BarTracker.initTracker()
  25.     BarTracker.restorePosition()
  26.     BarTracker.updateVisibility()
  27.     for i=1, 1, 1 do
  28.         d("Putting slot")
  29.         local slot = wm:CreateControlFromVirtual("Bar_Slot_" .. i, BarTracker.guiFront, BarTracker.guiTemplate)
  30.         slot:SetAnchor(TOPLEFT, BarTracker.guiFront, TOPLEFT, 0, 0)
  31.         slot:SetHidden(false)
  32.         slot.tex = slot:GetNamedChild("Tex")
  33.         slot.tex:SetTexture("art/icons/ability_templar_purifying_light.dds")
  34.     end
  35. end

Currently I can see the backdrop but the textures aren't displaying. Through DebugLogViewer I can see the print and no errors.
  Reply With Quote
06/12/20, 10:55 PM   #4
Dolgubon
 
Dolgubon's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2016
Posts: 408
So first, you'll want to remove the anchor from the texture in the xml. Adding an anchor does NOT replace the first one; it adds it. When there's two anchors, it puts the control between those two spots.e.g.
Anchor1 <<control fills this area >> Anchor2
Anchor1 << control still fills this area >> Anchor2


I don't think that's the cause of the error though, and I'm not entirely certain what is causing it.


Try getting zgoo if you don't already have it, then do /zgoo Bar_Slot_1
Check the GetChildren function's output, might help.
  Reply With Quote
06/13/20, 05:46 AM   #5
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
When the texture shows but is white your path to the texture is wrong.
You can check the path with Texture It addon ingame. Or Black book browser outside the game in the game source files (including preview).

If the texture is not shown at all and it's a custom dds file restart the client but delete file shadercache_cooked in the live folder after closing the client!
  Reply With Quote
06/13/20, 07:35 AM   #6
QuantumPie
AddOn Author - Click to view addons
Join Date: Sep 2019
Posts: 32
Good to know Zgoo is a thing. I checked the component and noticed GetNamedChild was Blacklisted so I switched to using GetChild. The updated snippet is:

Lua Code:
  1. local slot = wm:CreateControlFromVirtual("Bar_Slot_" .. i, BarTracker.guiFront, BarTracker.guiTemplate)
  2. slot:SetAnchor(TOPLEFT, BarTracker.guiFront, TOPLEFT, 0, 0)
  3. slot:SetHidden(false)
  4. local tex = slot:GetChild(1)
  5. tex:SetTexture("/esoui/art/icons/ability_templar_purifying_light.dds")

Upon inspecting the texture component, GetTextureFileName now returns the correct path (as opposed to empty string) but I still don't see the texture, nor a white square. I have also removed the anchor within the texture component from the XML file.

Here is what the UI looks like:
  Reply With Quote
06/13/20, 07:39 AM   #7
QuantumPie
AddOn Author - Click to view addons
Join Date: Sep 2019
Posts: 32
Oh! I see the icon at the top left of my screen. I'll work on fixing that.

EDIT:
Adding the anchor back in the XML texture fixed it (along with changing LEFT to TOPLEFT for both point and relPoint). I'm assuming though there is something wrong with how I structured it overall? I now can't seem to lie two textures side by side by increasing the loop to i=2 via:

Lua Code:
  1. local temp = BarTracker.guiFront;
  2.     local relPoint = TOPLEFT
  3.     for i=1, 2, 1 do
  4.         d("Putting slot")
  5.         d(relPoint)
  6.         local slot = wm:CreateControlFromVirtual("Bar_Slot_" .. i, BarTracker.guiFront, BarTracker.guiTemplate)
  7.         slot:SetAnchor(TOPLEFT, temp, relPoint, 0, 0)
  8.         slot:SetHidden(false)
  9.         local tex = slot:GetChild(1)
  10.         tex:SetTexture("/esoui/art/icons/ability_templar_purifying_light.dds")
  11.         temp = slot;
  12.         relPoint = TOPRIGHT
  13.     end

I got a much better feel for Anchors from a page on the wiki but I don't see where my logic is flawed.

Last edited by QuantumPie : 06/13/20 at 08:11 AM.
  Reply With Quote
06/13/20, 09:20 AM   #8
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
From your code it looks liek it should anchor properly. Bar_Slot_1's topleft to your TLC control's topleft (I assume BarTracker.guiFront is your TLC?) and Bar_Slot_2's topleft to Bar_Slot_1's topright.
Not sure why it does not show then.
Does your template of the slot contain any anchors? I see your code got them commented above maybe you have added them again?
Then always call slot:ClearAnchors() before setting new ones.

You can also try merTorchbug (like zgoo but with more features) as you are easy able to change the hidden state of a control you inspect.
Try /tbug Bar_Slot_1. e.g. and set the hidden state (via right click context menu on this ttaribut) to true and check if you are able to see your Bar_Slot_2 then. Or inspect Bar_Slot_2 and check what the anchor and the left, top values are.

btw: You should directly start to learn to use unique names for your controls, liek starting with your addon name e.g.
Bar_Slot_1 is not very unique and could be reused in other addons as well, so better use something like "MyAddonName_Bar_Slot_1"


And another hint instead of using a fixed child index to get the texture control:
Code:
local tex = slot:GetChild(1)
The texture could also be something else than always child 1!

You can use WINDOW_MANAGER:GetControlByName(parent, suffixOfChild) as well, so it would be
Lua Code:
  1. local tex = WINDOW_MANAGER:GetControlByName(slot, "Tex") --where "Tex" is the suffix of your textureControl in the XML, could be "Image" or "Texture" or "Icon" or whatever you have chosen in your XML or lua to create the control.


Another way to use the child index 1 would be :
Lua Code:
  1. local tex = WINDOW_MANAGER:GetControlByName(slot, 1)

Last edited by Baertram : 06/13/20 at 09:26 AM.
  Reply With Quote
06/13/20, 03:03 PM   #9
QuantumPie
AddOn Author - Click to view addons
Join Date: Sep 2019
Posts: 32
Thanks for all the assistance everyone provided! I finally managed to get it working
  Reply With Quote
06/13/20, 07:06 PM   #10
Dolgubon
 
Dolgubon's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2016
Posts: 408
Originally Posted by QuantumPie View Post
Good to know Zgoo is a thing. I checked the component and noticed GetNamedChild was Blacklisted so I switched to using GetChild.
That function is manually blacklisted only in zgoo, and there's no reason not to use it within your own addons. Personally, I like it more than just GetChild, because it is a little more robust to code changes. Like, if you change the order of adding stuff, it's not gonna break. Also, it's a bit more expressive as well.
  Reply With Quote
06/13/20, 08:06 PM   #11
Scootworks
 
Scootworks's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2014
Posts: 312
i do prefer

Lua Code:
  1. control:GetNamedChild("_Front")
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » Struggling to understand inherritence

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