+ Reply to Thread
Results 1 to 12 of 12

Thread: [Guide] Gadgets: Unit Frame Templates

  1. #1
    Sword of Telara DoomSprout's Avatar
    Join Date
    Apr 2011
    Posts
    876

    Default [Guide] Gadgets: Unit Frame Templates

    G A D G E T S
    UNIT FRAME TEMPLATE GUIDE

    Gadgets on RiftUI | Gadgets on Curse

    Note: This is currently (very!) incomplete, and is just a place holder. I was inspired by seeing the work other people are already doing creating templates to make a start on documenting how to do it. I will be providing a proper skeleton addon as a starting point for creating your own unit frames. The code here needs to be part of an addon with a dependency on Gadgets - I will be explaining how to do this.

    To create a unit frame template, start by declaring the template:

    Code:
    local MyFrame = WT.UnitFrame:Template("MyFrame")
    MyFrame.Configuration.Name = "My Unit Frame"
    MyFrame.Configuration.RaidSuitable = true
    MyFrame.Configuration.FrameType = "Frame"
    MyFrame.Configuration.Width = 150
    MyFrame.Configuration.Height = 50
    MyFrame.Configuration.Resizable = { 100, 50, 300, 100 }
    Doing this tells Gadgets about your template, and gives it some important information it needs to get things set up:

    - It registers a new template called "MyFrame", with the descriptive name "My Unit Frame".
    - It tells Gadgets that it's OK to use this as a raid frame
    - The base element for the unit frame is a "Frame". Don't worry about this unless you're getting really advanced.
    - The default size is 150x50 pixels
    - The frame can be resized, from 100x50 up to 300x100 pixels

    Now declare the template's constructor function:

    Code:
    function MyFrame:Construct(options)
    end
    At this point, the template will work, but it won't do very much, as we're not actually displaying anything, so we'll create the most basic unit frame possible - just a health bar and the unit's name. Change the Construct() function to look like this:

    Code:
    function MyFrame:Construct(options)
    
        self:SetBackgroundColor(0,0,0,1)
    
        self:CreateElement({
            id="barHealth", type="Bar", parent="frame",
            attach = 
            {
                { point="TOPLEFT", element="frame", targetPoint="TOPLEFT", offsetX=1, offsetY=1 },
                { point="BOTTOMRIGHT", element="frame", targetPoint="BOTTOMRIGHT", offsetX=-1, offsetY=-1 },
            },
            growthDirection="right",
            binding="healthPercent", color={r=0,g=0.7,b=0,a=1}, media="wtBantoBar",
            backgroundColor={r=0, g=0, b=0, a=1},
        })
    
        self:CreateElement({
            id="labelName", type="Label", parent="frame", layer=10,
            attach = {{ point="CENTER", element="frame", targetPoint="CENTER", offsetX=0, offsetY=0 }},
            visibilityBinding="name",
            color={r=1,g=1,b=1,a=1},
            text="{name}", default="", linkedHeightElement="barHealth", linkedHeightScale=0.45, maxLength=9,
        })
        
    end
    Here, we are giving our unit frame a background colour of black (0,0,0,1), and then creating two new elements, called "barHealth" and "labelName".

    barHealth is of type "Bar", which means it is a health/mana/etc bar. It sits directly on top of the unit frame (parent="frame"), and is attached as follows:
    The top left corner is attached to the top left corner of the frame, with an offset of 1 pixel right and down.
    The bottom right corner is attached to the bottom right corner of the frame, with an offset of 1 pixel left and up.

    The bar will grow from left to right (growthDirection="right")

    The bar uses the texture "wtBantoBar", which must be registered with the media library (more on this later)

    The bar is coloured green. This only has an effect if the chosen texture is designed to be tinted (it needs an alpha channel that allows background colours to show through).

    The bar has a background colour of black.

    The bar is bound to the unit property "healthPercent". Elements within a unit frame can be bound to any property of a unit, and additional custom properties can also be defined (see Virtual Properties later). The RIFT API does not provide a healthPercent value for a unit, but it is defined as a virtual property within Gadgets, so it is always available. A Bar element must always be bound to a percentage property (one that has a value between 0 and 100).


    labelName is of type "Label", which is how we add text to a unit frame.

    It specifies a visibilityBinding, which means the element is only visible if the property "name" has a value.

    It specifies text of "{name}". Within a label element, any unit properties can be included as a token within braces. For example, we could specify "Name: {name} Calling: {calling}", and the text would include the unit's name and calling.

    Rather than specify a fontSize (which you can do), here I am specifying a linkedHeightElement and and linkedHeightScale. These are the properties that allow us to scale a font based on the height of another element. In this case, the name will have a font size 0.45 x the height of the health bar.

    Finally, we specify a maxLength value, which prevents the text in the label from exceeding 9 characters in length.

    The end result:

    [Guide] Gadgets: Unit Frame Templates-reallysimpleunitframe.png

    Admittedly not the most stunning unit frame out there, but hopefully it gives an idea of how to get started. Feel free to have a look in "Gadgets/wtLibUnitFrame/Templates" in the main addon to get an idea of how to put together far more complex (and useful!) frames.


    * Unfinished work in progress...

    There are many more element types to play with, and various options to allow you to customize exactly how information is displayed. I will be massively expanding this topic to cover the various aspects of the unit frame templates over the next few days.
    Last edited by DoomSprout; 08-14-2012 at 02:29 PM.

    Gadgets: Unit Frames and Other Stuff for RIFT

  2. #2
    Sword of Telara DoomSprout's Avatar
    Join Date
    Apr 2011
    Posts
    876

    Default

    Reserved for expansion - Element types & Media Library
    Last edited by DoomSprout; 08-14-2012 at 02:16 PM.

    Gadgets: Unit Frames and Other Stuff for RIFT

  3. #3
    Sword of Telara DoomSprout's Avatar
    Join Date
    Apr 2011
    Posts
    876

    Default

    Virtual Properties

    When binding properties to a unit frame, sometimes a unit doesn't provide the data we want. A good example of this is a unit's percentage health; this isn't available in a standard unit, but it is needed for binding to bars in a template.

    This is where virtual properties come in. They allow you to create additional properties on a unit, which are calculated from the unit's data. You create a virtual property as follows:

    Code:
    WT.Unit.CreateVirtualProperty("healthPercent", { "health", "healthMax" }, 
        function(unit)
            if unit.health and unit.healthMax and unit.healthMax > 0 then
                return (unit.health / unit.healthMax) * 100 
            else 
                return nil
            end 
        end)
    This particular property is taken straight from the Gadgets framework so it's already there, but it serves as a good example.

    Here, we are defining a new unit property called "healthPercent", which is dependent on the "health" and "healthMax" properties. Whenever either of these values changes, the function will be called to calculate our virtual property. In this instance, we calculate the unit's percentage health, or return nil if we don't have enough data to provide a value.

    Another example, also taken straight from the Gadgets framework, is the creation of the "resource" property. This takes all of the possible resources a unit can have (mana/energy/power), and turns them into a single property "resource", which means we don't have to worry about which resource the unit uses when binding in a template:

    Code:
    WT.Unit.CreateVirtualProperty("resource", { "mana", "power", "energy" }, 
        function(unit) 
            return unit.mana or unit.energy or unit.power 
        end)
    This property is calculated whenever any of the possible resource values changes, and it simply returns whichever one of the three values actually exists.
    Last edited by DoomSprout; 08-15-2012 at 12:31 AM.

    Gadgets: Unit Frames and Other Stuff for RIFT

  4. #4
    Sword of Telara DoomSprout's Avatar
    Join Date
    Apr 2011
    Posts
    876

    Default

    Advanced Data Binding

    Note: You don't need to know any of this to create a template. This information is intended for addon developers using the Gadgets framework as part of their own addons.

    A UnitFrame is not a gadget; UnitFrames exist at a lower level in the overall framework, and don't know anything about gadgets at all. This means you can use UnitFrame functionality in any addon, even if that addon isn't providing any actual gadgets.

    At its core, a UnitFrame is an object that watches a specific unit specifier, and handles the binding of data on the unit it's watching to function calls. To create a UnitFrame, you need to specify the unit specifier to watch:

    Code:
    local uf = WT.UnitFrame:Create("player.target")
    Once you've got a UnitFrame object, you can bind unit properties to method calls (it is this functionality that underpins the unit frame template mechanism). This is done using the method 'CreateBinding':

    function WT.UnitFrame:CreateBinding(property, bindToObject, bindToMethod, default, converter)

    Code:
    local function NameChanged(unitframe, value)
        print("Binding Fired: " .. unitframe.UnitSpec .. " name = " .. value)
    end
    
    local uf = WT.UnitFrame:Create("player.target")
    
    uf:CreateBinding("name", uf, NameChanged, "")
    What we're doing here is defining a method that will be called whenever the bound property changes, and then creating a binding for the property 'name'. In this example, I am specifying the unit frame itself as the object, but this is not usually the case. Here is another example, where we bind a unit's health to a text frame:


    Code:
    local ctx = UI.CreateContext("ctx")
    local textFrame = UI.CreateFrame("Text", "textFrame", ctx)
    textFrame:SetPoint("CENTER", UIParent, "CENTER")
    
    local uf = WT.UnitFrame:Create("player.target")
    
    uf:CreateBinding("health", textFrame, textFrame.SetText, "", tostring)
    What will happen here is every time the unit's health changes, SetText() will be called on the text frame with the unit's health as the piece of text to set. You'll notice I've added an extra argument, 'tostring', to the binding call. This is the converter function, which is called with the property value to allow you to alter the value before it gets passed onto the binding method. In this instance, I'm using tostring, which is a built in Lua function to turn the health value (a number) into a string.


    * Incomplete, more to come...
    Last edited by DoomSprout; 08-15-2012 at 01:56 AM.

    Gadgets: Unit Frames and Other Stuff for RIFT

  5. #5
    Shield of Telara Nerva3x0's Avatar
    Join Date
    Jul 2012
    Posts
    732

    Default

    This is very cool, TY. I have been attempting to learn Lua, not very successfully . Anyway I have been adding extra textures to your current Unit Frames, and this is an easier way of doing it.
    Last edited by Nerva3x0; 08-14-2012 at 02:45 PM.

  6. #6
    Champion thoroar's Avatar
    Join Date
    Oct 2011
    Posts
    505

    Default

    Quote Originally Posted by Nerva3x0 View Post
    This is very cool, TY. I have been attempting to learn Lua, not very successfully . Anyway I have been adding extra textures to your current Unit Frames, and this is an easier way of doing it.
    Agreed! A full guide will be very helpful while I am still trying to grasp the language! Keep it up

    Hopefully nerfedwar will finish his at somepoint !
    Capes
    Cloaks

    Thoroar - Narcissia - Ricroar - Swimella
    I'm @Icewatch, /hug me!

  7. #7
    Shield of Telara Nerva3x0's Avatar
    Join Date
    Jul 2012
    Posts
    732

    Default Player Portrait

    Do we have access to the 3d or even a static player portrait, like the one in the default frames?

  8. #8
    RIFT Guide Writer Noshei's Avatar
    Join Date
    Feb 2011
    Posts
    1,886

    Default

    Quote Originally Posted by Nerva3x0 View Post
    Do we have access to the 3d or even a static player portrait, like the one in the default frames?
    nope, not available to us through the addon API.

  9. #9
    Sword of Telara DoomSprout's Avatar
    Join Date
    Apr 2011
    Posts
    876

    Default

    Bumping this to bring it onto the front screen for Redcruxs...

    Documentation is kinda scarce. I started this thread a while ago, which covers creating templates for unit frames. I'll read through what I put, and see if I can expand on bits of it.

    For what you're wanting to do, a template similar to the example in this guide, combined with a pair of virtual properties to calculate the EHP values, might be all you need.

    Gadgets: Unit Frames and Other Stuff for RIFT

  10. #10
    Soulwalker
    Join Date
    Aug 2013
    Posts
    8

    Default

    Any ideas about how to change font type ? (either the global font of a template, or for a specific label)

    Edit : Oh well, I think I figured out how it works. Adding the font file, referencing the media resource, and using the
    Code:
    font = "FontID"
    parameter in the label parameter field.
    Last edited by s0ren; 08-06-2013 at 01:55 AM.

  11. #11
    Sword of Telara DoomSprout's Avatar
    Join Date
    Apr 2011
    Posts
    876

    Default

    Quote Originally Posted by s0ren View Post
    Any ideas about how to change font type ? (either the global font of a template, or for a specific label)

    Edit : Oh well, I think I figured out how it works. Adding the font file, referencing the media resource, and using the
    Code:
    font = "FontID"
    parameter in the label parameter field.
    That sounds about right

    Yes, you need to add the font to the media library to tell Gadgets that it exists, and then you can specify the font on any Label element. There is currently no concept of setting a global font for a template, though this might be a useful thing to add.

    Gadgets: Unit Frames and Other Stuff for RIFT

  12. #12
    Soulwalker
    Join Date
    Aug 2013
    Posts
    8

    Default

    That would be very useful in fact, and a being able to change it right from the ingame configuration panel would be even better ! Good job for the whole addon, btw, a truly great one.

    For now, I'll be using the good old BigNoodleTitiling font that I used to have back in World of Warcraft
    Last edited by s0ren; 08-06-2013 at 02:34 AM.

+ Reply to Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts