Skip to content
asakawa edited this page Mar 22, 2022 · 30 revisions

This page contains a brief(ish) explanation of how users should use the various code blocks in the WA interface, what WA sends in to the code block and what it expects to be provided by the user. Links to each section are given in-game when the "help" button is clicked at the bottom of each expanded code editor. If you're arriving at this page and reading from this intro then please understand the info is given in that context.

If any of the info provided is insufficient or confusing then please don't hesitate to join the Discord (linked in the side-bar) to discuss ways in which the info could be given more clearly.

Actions

On Init

  • This is not a code-block in which you are defining a function (no function()...end construction required)
    • No Args sent in to the code block.
    • No return expected.

Init runs once when the aura is first loaded then never again until a UI reload/restart or if changes made to this code block or to Custom Options. It does not run each time the Aura is loaded, a common misconception that can cause problems.

This code block is exceptionally useful for creating settings (any settings that users may want to alter should be done with Custom Options), tables of data, or functions. Anything that will be used throughout your Aura, or repeatedly by a function. Create variables like this in the aura_env table.

If the Aura you're making produces clones then this code block runs before they exist and so aura_env.state won't exist and aura_env.region will refer to the "base" Aura, not any clones you create later.

Further Reading
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

On Show

  • This is not a code-block in which you are defining a function (no function()...end construction required)
    • No Args sent in to the code block.
    • No return expected.

On Show runs once when the Aura as a whole changes from not being active to being active. Then it will not run again until the Aura hides, and shows again.

If the Aura you're making produces clones, then this code block will run for each clone that is shown and aura_env.state and aura_env.region will carry that clone's info.

Further Reading
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

On Hide

  • This is not a code-block in which you are defining a function (no function()...end construction required)
    • No Args sent in to the code block.
    • No return expected.

On Hide runs once when the Aura as a whole changes from being active to not being active. Then it will not run again until the Aura shows, and hides again.

If the Aura you're making produces clones, then this code block will run for each clone that hides and aura_env.state and aura_env.region will carry that clone's info.

Further Reading
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Chat Message - Custom Code

This code block is accessed by using the Chat Message option, with %c in the Message text. The string(s) you return will be inserted into the message that you send.

Although it's likely that Custom Text functions in Actions will be much simpler than those in Display, all the info is the same so see below for extensive details.


Display

Custom Text

Args

If the trigger currently providing Dynamic Info uses "timed" duration info (e.g. buff duration) then:
function(expirationTime, duration, progress, formatedDuration, name, icon, stacks)
  • expirationTime - number When the displayed timer will expire, relative to GetTime().
  • duration - number The total number of seconds, e.g. 123.
  • progress - string A formatted string showing remaining duration, equivalent of the %p text replacement.
  • formatedDuration - string A formatted string showing minutes if applicable, e.g. 2:03, equivalent of the %t text replacement.
  • name - string Whatever string the active trigger carries on its Name Info, equivalent of the %n text replacement.
  • icon - string A formatted string with the Escape Sequences needed to display the Dynamic Info's icon in text, equivalent to the %i text replacement.
  • stacks - number The value carried by the Dynamic Info's Stacks, equivalent to %s.
If the trigger currently providing Dynamic Info uses "static" duration info (e.g. health values) then:
function(total, value, value, total, name, icon, stacks)
  • total - number The total or max value, equivalent to the %t text replacement .
  • value - number The current value carried by dynamic Info, equivalent to the %p text replacement.
  • value and total are repeated just to match argument positions with those with timed info.
  • Other args are as above.
Expected return:
return string[, string, string]
  • You can return multiple values. If you do so they will be output in your text using %c1, %c2, and so on.
  • You can return nil, it will be handled as an empty string.
"Update Custom Text On..."

Above this code block in the interface is a setting "Update Custom Text On...":

  • Trigger Update will fire the custom function when the Dynamic Info from any trigger in the Aura changes in any way. It will not fire when a custom trigger returns true from its trigger function, unless that custom trigger also adjusts one of the Dynamic Infos it carries.
  • Every Frame will fire the custom function every time the screen redraws (your Frames Per Second). This should be avoided where possible, since it means it will often be running when there is no change to update. When it is necessary though, don't worry too much, just code your function with efficiency in mind. Any application where you're outputting a timer will inevitably require "Every Frame".
Notes
  • While a pretty thorough explanation of args is given above, most uses of Custom Text won't necessarily use them. They can't be guaranteed to always carry the value you need meaning you've got to do quite a lot of type checking before using them. As such the usual recommendation is to use values from aura_env.state or aura_env.states directly.
  • On a Timed Aura, despite looking like a number when below a minute, the "progress" value is actually a formatted string and shouldn't be used for arithmetic. If you need a remaining duration in your custom function then calculate it yourself, e.g.
function()
  if aura_env.state and aura_env.state.duration and aura_env.state.duration > 0 then
    local remaining = aura_env.state.expirationTime - GetTime()
    return remaining > 3600 and ceil(remaining/3600).."h" or remaining > 60 and ceil(remaining/60).."m" or floor(remaining)
  end
end
Useful further reading:
  • Text Replacements
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Custom Anchor Function

  • No args are sent in to the function.
  • It is fired on Trigger Update.
  • Expected return is a reference to a UI Frame. This frame can be a WA Aura/region, a Blizzard UI element, or another Addon's frame.

This example, used with a Status - Cast trigger with setting Unit = Player, will anchor the region to your target's nameplate

function()
    if aura_env.state.destUnit then
        return C_NamePlate.GetNamePlateForUnit(aura_env.state.destUnit)
    end
end
Notes

There are quite a few custom anchoring options:

  • If the thing(s) you're anchoring are never going to be attached to the same frame, and so do not need to adjust/offset from one another, then use Anchored To = Custom in the Display tab to define the frame (and you can forgo using a Dynamic Group).
  • If the things you're anchoring may be attached to the same frame, and so do need to adjust dynamically so as not to overlap, but you do not need direct control over the precise offsets for each region, then use a Dynamic Group and Group By Frame = Custom Frames.
  • If you need direct control over the anchor and offset of each Aura/Clone, then you need to use a Dynamic Group and Grow = Custom.
Further Reading
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Trigger

Custom Activation

  • One argument sent in to the function: the triggers table, an array containing a boolean for the activated state of each trigger in the Aura.
  • Runs when any trigger in the Aura's "active" state changes from false to true or vice versa.
  • Expected return is a single Boolean for whether the Aura should show or not.

Example - this example function would display the aura if trigger 1 is active and at least one of triggers 2 or 3 is also active.

function(triggers)
  return triggers[1] and (triggers[2] or triggers[3])
end

See this page for general info on Activation.

Custom Dynamic Info

  • One argument sent in to the function: the triggers table, an array containing a boolean for the activated state of each trigger in the Aura.
  • Runs when the "active" state of any trigger in the Aura changes from false to true or vice versa.
  • Expected return is a number of a trigger whose Dynamic Info should be displayed.

Example - this example function would display Dynamic Info from trigger2 while trigger3 is active, and that of trigger1 otherwise.

function(triggers)
  return triggers[3] and 2 or 1
end

See this page for general info on Dynamic Info.

Custom Trigger

  • Args sent in to the function depend on the trigger type, see below.
  • Expected return is a boolean for whether the trigger should be active or not.
Args
  • If you use Custom - Status - Every Frame, then no args will be sent in to the function.
  • If you use Custom Status - Event(s) - or Custom - Event(s) - , then WA will send the event name as the first arg, followed by the event's own args, in to your function.
  • If you use Custom - Trigger State Updater then WA will always send the allstates table as the first arg.
    • If you use Every Frame then there will be no following args.
    • If you use Event(s) - , then the second arg will be the event's name, followed by the event's own args.
Examples

Using Custom - Status - Event - UNIT_HEALTH

function(event, unit)
    if unit == "player" then
        return UnitHealth("player") > 1000
    end
end

Using Custom - Event - CLEU

function(event, timestamp, subEvent, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, ...)
    if subEvent == "SPELL_CAST_SUCCESS" and sourceGUID == UnitGUID("player") then
        return true
    end
end

Using Custom - TSU - Event - UNIT_HEALTH

function(allstates, event, unit)
    if unit == "player" then
        allstates[""] = {
            show = true,
            changed = true,
            progressType = "static",
            value = UnitHealth("player"),
            total = UnitHealthMax("player"),
        }
        return true
    end
end
Further reading:

Custom Variables

This is a special code-block in which you are not defining a function (no function()...end construction required), but defining a table which tells the addon which variables from the trigger you want to make available in Conditions.

Example
{
    stacks = true,
    myVar = {
        display = "My Var",
        type = "number",
    },
    unit = "string",
}
Further Reading
  • TSU Wiki Article - As part of a TSU trigger, Custom Variables is complex but fully outlined in this link.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Custom Untrigger

  • Args sent in to this function are the same as those in the Trigger.
  • Expected return is a boolean. Return true if the trigger should untrigger, false if it should remain active.
  • The Untrigger function only runs if the trigger returns false/nil.
Further Reading
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Duration Info

  • One arg sent in, the "trigger" table. This arg is sent for internal WA reasons and is unlikely to ever be useful to users.
  • Expected return - Duration Info can either carry a timer or a static value/total, the values returned are slightly different in each case.
Returned values
  • Timed info should simply return two values return duration, expirationTime.
    • duration - number, total duration of the timer in seconds.
    • expirationTime - number, relative to GetTime(), when the timer will expire.
  • Static info should return three, return value, total, isStatic.
    • value - number, the current value.
    • total - number, the total or maximum value.
    • isStatic - boolean, this simply tells WA that the previous 2 values given should be interpreted as Static Duration rather than Timed.
Further Reading:
  • Dynamic Info.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Name Info

  • One arg sent in, the "trigger" table. This arg is sent for internal WA reasons and is unlikely to ever be useful to users.
  • Expected return is a single string.
Further Reading:
  • Dynamic Info.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Icon Info

  • One arg sent in, the "trigger" table. This arg is sent for internal WA reasons and is unlikely to ever be useful to users.
  • Expected return is a valid texture path. This can be in the form of an iconID, or a path string.
  • This function is used for Icon and Progress Bar Aura Types, while Icon Info is used for Texture and Progress Texture Aura Types.
Examples:
function()
    return GetSpellTexture(123456)
end
function() 
     return "Interface\\TargetingFrame\\UI-RaidTargetingIcon_1"
end

IconIDs can also be found through a database site like Wowhead (example image) or WoW.tools (example link).

Further Reading:
  • Dynamic Info.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Texture Info

See Icon Info.

  • This function is used for Texture and Progress Texture Aura Types, while Icon Info is used for Icon and Progress Bar Aura Types.
Further Reading
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Stack Info

  • One arg sent in, the "trigger" table. This arg is sent for internal WA reasons and is unlikely to ever be useful to users.
  • Expected return is a single number.

The way the Conditions tab processes this Info is as a number so it will cause errors if you try to return a string or other value.

Further Reading:
  • Dynamic Info.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Overlay Info

  • One arg sent in, the "trigger" table. This arg is sent for internal WA reasons and is unlikely to ever be useful to users.
  • Expected return - Overlays can behave in two distinct ways and the returned values required in each case differ.
Returned values
  • For non-moving overlays return left_value, right_value.
    • The values are numbers and relative to the duration of "timed" Duration Info, or the total of a "static" Duration Info.
    • you define both points of the Overlay.
  • For moving overlays return direction, width.
    • direction - string, Either "forward" or "backward", setting whether the Overlay should lead or trail the progressing edge of the Aura.
    • width - number, relative to the duration or total defined in the Duration Info, setting the size of the Overlay.

The Colours and Clipping Behaviours of each Overlay can be set in the Display tab.

Further Reading:
  • Dynamic Info.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Conditions

Run Custom Code

  • This is not a code-block in which you are defining a function (no function()...end construction required)
    • No Args sent in to the code block.
    • No return expected.

This function runs once when the Condition you made is passed, then not again until the Condition becomes false then true again. It also, of course, can't undo itself - if you use it to make a change that ought to return to the standard, then you'll need to add Conditions to handle that too.

Custom Check

  • This function is called to check if a condition should be activated
  • It receives one argument, an array containing the states across all triggers for a given aura.

For example, to compare the remaining time of trigger 1 and trigger 2 use:

function(states)
  if states[1].expirationTime and states[2].expirationTime then
    return states[1].expirationTime < states[2].expirationTime
  end
end

The function is automatically called every time any state changes. Extra WoW events that should re-evaluate this condition can be specified in the text field above.

Further Reading
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Chat Message - Custom Code

This code block is accessed by using the Chat Message option, with %c in the Message text. The string(s) you return will be inserted into the message that you send.

Although it's likely that Custom Text functions in Actions will be much simpler than those in Display, all the info is the same so see below for extensive details.


Animation

Alpha (Opacity)

Args
  • progress A number value between 0 and 1 which represents how far along the animation is. Main and Finish animations start at 0 and end at 1, while Start animations start at 1 and end at 0.
  • start The Alpha value that is defined as "normal" for the display, expressed as a value between 0 (invisible) and 1 (completely opaque). This is the value you set in the Display tab.
  • delta The difference between the "normal" alpha of the display and the alpha value specified for in the Animation settings. For example, if a display is set to 100% alpha normally, and its Alpha animation is set to 33%, then "delta" would be -0.66.
Expected Returns
  • alpha An Alpha animation function should return a single number value between 0 and 1, the alpha value that the display should have at the current point in the animation.
Example

The "Normal" Alpha animation path, which simply transitions from one Alpha value to another in a linear fashion, looks like this:

function(progress, start, delta)
  return start + (progress * delta)
end
Further reading
  • Custom Animations.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Translate (Position)

Args
  • progress A value between 0 and 1 which represents how far along the animation is. Main and Finish animations start at 0 and end at 1, while Start animations start at 1 and end at 0.
  • startX The x coordinate that is defined as "normal" for the display (specifically, the x coordinate of its anchor point), expressed in pixels. This is the value you set in the Display tab.
  • startY The y coordinate that is defined as "normal" for the display (specifically, the y coordinate of its anchor point), expressed in pixels. This is the value you set in the Display tab.
  • deltaX The value specified by the animation using the "X Offset" slider in the Animation settings.
  • deltaY The value specified by the animation using the "Y Offset" slider in the Animation settings.
Expected Returns
  • x The resulting x coordinate of the display.
  • y The resulting y coordinate of the display.
Example

The "Normal" Translate animation path, which simply transitions from one position to another in a straight line, looks like this:

function(progress, startX, startY, deltaX, deltaY)
  return startX + (progress * deltaX), startY + (progress * deltaY)
end
Notes

A display's x and y coordinates are defined in terms of the distance between its reference anchor point and its self anchor point, both of which can be set in the Display tab. In WoW, x coordinates go from 0 at the left side of the screen to a positive value at the right side of the screen, and y coordinates go from 0 at the bottom of the screen to a positive value at the top of the screen. This is vertically inverse compared to many coordinate systems used in programming.

Further reading
  • Custom Animations.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Scale (size)

Args
  • progress A value between 0 and 1 which represents how far along the animation is. Main and Finish animations start at 0 and end at 1, while Start animations start at 1 and end at 0.
  • startX The "normal" scale of the display in the x direction. This is always 1.
  • startY The "normal" scale of the display in the y direction. This is always 1.
  • scaleX The value specified by the animation using the "X Scale" slider in the Animation settings.
  • scaleY The value specified by the animation using the "Y Scale" slider in the Animation settings.
Expected Returns
  • scaleX The resulting scale of the display in the x direction.
  • scaleY The resulting scale of the display in the y direction.
Notes

An aura's scale in either the x or y direction is defined in relation to its normal size. This means that a display that is normally 200x200 pixels, if under a Scale animation whose current values are 1.5 and 0.8, will be 300x160 pixels.

Note that the scaleX and scaleY values passed to the Scale function are interpreted as being absolute values which denote the eventual maximum scale of the animation, not the difference between the original scale (which is always 1x1) and the end scale. This is a different behavior than the rest of the animation types.

Also note that Scale animations will differ slightly based on the display's anchor point, which will not change positions. A display anchored by its center will scale from the center, whereas a display anchored by a corner will scale from that corner.

Example

The "Normal" Scale animation path, which simply scales from one size to another in a linear fashion, looks like this:

function(progress, startX, startY, scaleX, scaleY)
  return startX + (progress * (scaleX - startX)),  startY + (progress * (scaleY - startY))
end
Further reading
  • Custom Animations.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Rotate

Args
  • progress A value between 0 and 1 which represents how far along the animation is. Main and Finish animations start at 0 and end at 1, while Start animations start at 1 and end at 0.
  • start The Rotation value that is defined as "normal" for the display, expressed in degrees. This is the value you set in the Display tab.
  • delta The rotation value specified for the animation, using the slider in the Animation settings.
Expected Returns

rotation The rotation value that the display should have at the current point in the animation.

Notes

Texture displays are the only display type that is able to rotate (and only if Allow Full Rotation is enabled).

Example

The "Normal" Rotate animation path, which simply transitions from one Rotation value to another in a linear fashion, looks like this:

function(progress, start, delta)
  return start + (progress * delta)
end
Further reading
  • Custom Animations.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Color

Args
  • progress A value between 0 and 1 which represents how far along the animation is. Main and Finish animations start at 0 and end at 1, while Start animations start at 1 and end at 0.
  • The RGBA color values that define "normal" for the display. This is what you set in the Display tab.
    • r1
    • g1
    • b1
    • a1
  • The RGBA color values specified for the animation, using the Color Picker in the Animation Settings.
    • r2
    • g2
    • b2
    • a2
Expected Returns
  • The RGBA color values that the display should have at the current point in the animation.
    • r
    • g
    • b
    • a
Notes

Color values for frames in WoW are "percent" values between 0 and 1, not hex values as you might have used when formatting text. If you're working from 0-255 values, then you can simply divide them (return 73/255, 122/255, 255/255, 255/255).

Example

The "Color" animation path, which simply transitions from one color value to another in a linear fashion, looks like this:

function(progress, r1, g1, b1, a1, r2, g2, b2, a2)
    return r1 + (progress * (r2 - r1)), g1 + (progress * (g2 - g1)), b1 + (progress * (b2 - b1)), a1 + (progress * (a2 - a1))
end
Further reading
  • Custom Animations.
  • aura_env - The aura_env table is effectively "global" to just the Aura in which you're working and provides a great deal of use to Custom Coders.

Group

Custom Sort

Args
  • regionDataA The regionData table for the first of the Group's children that you're sorting.
  • regionDataB The regionData table for the second of the Group's children that you're sorting.
Expected Returns
  • boolean Whether regionA should be sorted before regionB
Notes
  • See the main article for an explanation of what the regionData table contains.
  • Not explicitly explained in the above article, the state data is in the region table. So regionDataA.region.state.expirationTime would be the location of state info.
Example
function(a, b)
    return (a.region.state.expirationTime or 0) > (b.region.state.expirationTime or 0)
end

Grow

Args
  • newPositions - An empty table to be filled by you with positional data for the regions provided in the second arg.
  • activeRegions - An array of regionData objects in sorted order for all the regions that your Group will display.
Expected Returns

You don't have to return anything from the function, but you should fill the newPositions table with info for each of the regions defined in activeRegions. This can be defined in two distinct methods, depending on whether you're simply settings offsets from group's main anchor, or want to set a separate anchor frame and offsets for each region.

Simple Custom Offsets

Using the same index in newPositions as found in activeRegions, each index should be assigned a table value, of an array containing {x, y, show}:

  • x - number The horizontal offset for the region.
  • y - number The vertical offset for the region.
  • show - boolean Whether the region should be shown or hidden. This value can be ignored and will default to true if left out of the table. However, if you want to hide a region you can add false in to this third value to achieve that. This allows a measure of filtering at this "output" stage.
Example
function(newPositions, activeRegions)
    -- this function will produce a parabola shape
    local mid = #activeRegions / 2
    for i = 1, #activeRegions do
        newPositions[i] = {
            40 * (i - mid),
            0.5 * (i - mid)^2
        }
    end
end
Setting custom frames and offsets

You can also structure the newPositions table differently in order to anchor each region to a given frame, with whatever offsets you need. The structure would be:

newPositions[frame][regionData] = {x,y,show}

So, newPositions should contain tables for each frame you want to anchor child regions to. Those tables should be keyed using the frame's reference and contain entries for each child region anchored to that frame, each keyed using the regionData table from activeRegions with the value of an offsets array (this part is just as above in the Simple Custom Offsets section).

And example can be found in the main article.

Notes

The more complex method above is only needed if you specifically need to be able to set custom offsets on your child regions, while also anchoring them to differing, custom, frames. If you need to anchor children to different frames but can use a default Grow setting (e.g. they're anchored to nameplates but just growing to the right as more regions anchor), then you should use the Group By Frame option detailed below.

The two methods can not be mixed, i.e. you can't have some regions simply offset from the group's anchor while others are anchored to given frames.

There are quite a few custom anchoring options:

  • If the thing(s) you're anchoring are never going to be attached to the same frame, and so do not need to adjust/offset from one another, then use Anchored To = Custom in the Display tab to define the frame. (And can forgo using a Dynamic Group).
  • If the things you're anchoring may be attached to the same frame, and so do need adjust dynamically so as not to overlap, but you do not need direct control over the precise offsets for each region, then use a Dynamic Group and Group By Frame = Custom Frames.
  • If you need direct control over the anchor and offset of each Aura/Clone then you need to use a Dynamic Group and Grow = Custom.
Further Reading

Group by Frame

Args
  • frames An empty table that you will fill with info that WA uses to anchor the Group's children.
  • activeRegions An array containing regionData for each active child of the Group.
Expected Return

You don't need to return anything from this function. You are expected to fill the frames table with arrays keyed using frame references, containing the regionData for each anchored child region.

frames[frame] = {regionData, regionData, ...}
Example
function(frames, activeRegions)
    for _, regionData in ipairs(activeRegions) do
        local unit = regionData.region.state and regionData.region.state.destUnit
        if unit then
            local frame = C_NamePlate.GetNamePlateForUnit(unit)
            if frame then
                frames[frame] = frames[frame] or {}
                tinsert(frames[frame], regionData)
            end
        end
    end
end
Notes

There are quite a few custom anchoring options:

  • If the thing(s) you're anchoring are never going to be attached to the same frame, and so do not need to adjust/offset from one another, then use Anchored To = Custom in the Display tab to define the frame. (And can forgo using a Dynamic Group).
  • If the things you're anchoring may be attached to the same frame, and so do need adjust dynamically so as not to overlap, but you do not need direct control over the precise offsets for each region, then use a Dynamic Group and Group By Frame = Custom Frames.
  • If you need direct control over the anchor and offset of each Aura/Clone then you need to use a Dynamic Group and Grow = Custom.
Further Reading
Clone this wiki locally