vrtc / chorus (public) (License: CC0) (since 2023-08-12) (hash sha1)
World of Warcraft add-on stub. The overall goal is to create a specialized raid frame.
List of commits:
Subject Hash Author Date (UTC)
feat!: integrate party pets frame f34c334ca838ca8c26106f89fa7e088bf74af36b Vladyslav Bondarenko 2025-02-09 22:59:14
fix: add robustness check to button factories b7e195cf9623c0e7280a2a76d34de2f078373852 Vladyslav Bondarenko 2025-02-09 20:48:36
feat: integrate pet frame with raid profiles 856c7021197a301ab04428bc0dfff4eaa77a0a43 Vladyslav Bondarenko 2025-02-09 20:47:03
fix!: update pet frame correctly 3d9a3ac39962ca2e39f7a330abe74a229b822e4e Vladyslav Bondarenko 2025-02-09 00:56:36
feat: add pet frame stub 4cbc49b6720943fb9929f3bce34887d425c36629 Vladyslav Bondarenko 2025-02-08 23:21:15
fix: trigger unit button on mouse down 730a9f8483b0ccf6d8bccae71c1ab83bbae08920 Vladyslav Bondarenko 2025-02-08 18:41:46
doc: fix minor documentation markup issues fc0a3ac65c9a4682025639d416083bbfc690023f Vladyslav Bondarenko 2025-02-05 11:40:51
fix: move role widget 2832bd50f728bb89412aff98d8d1776ce102fb92 Vladyslav Bondarenko 2025-02-04 20:02:58
feat: aura duration of less than one second 9d2be37d502e438ebb1c79bc9278fd7f189ec8d3 Vladyslav Bondarenko 2025-02-04 19:29:50
feat!: add ready check widget 54f77e083a30b5d2ea3d7c0facc4f04ae5a50524 Vladyslav Bondarenko 2025-02-04 18:56:01
fix: add numerical identifiers to raid frames 7805568e6500ba652f5489a84d78697dc81d1017 Vladyslav Bondarenko 2025-02-04 18:54:04
fix: remove generated XML from small raid 9ec89db68e9d2304df118b2500e8675a941e699c Vladyslav Bondarenko 2025-02-04 18:52:50
fix: unit backdrop dimensions d677e35bebff554b26c4240c1a2cb2b0327f1cf3 Vladyslav Bondarenko 2025-02-03 21:10:07
fix: remove XML generators 0430f8d2cc9c7cf5ee22ae518f42e2ce85d5d5e7 Vladyslav Bondarenko 2025-02-03 20:20:52
feat: change aura tooltip graphics bf7cb7b9b19ffb4850d8e72d8352af75a5bdccfa Vladyslav Bondarenko 2025-02-02 22:52:58
fix!: aura tooltip aura buttons clearly visible dcebd82df00d5daee8d008c625e71d13c8da8c37 Vladyslav Bondarenko 2025-02-02 21:26:15
feat: bump version to 0.12.0-10 fffe025cfcfbe5ec0356d34cffdef1bfb62ea0af Vladyslav Bondarenko 2025-02-02 18:57:49
feat: allow aura tooltip to be dragged d4d699efa596b5bc5004873b3e41b50a09f4f3db Vladyslav Bondarenko 2025-02-02 18:56:00
feat!: create singleton aura tooltip 8e8e798543ef100a71ba2a9d212e66b1ddd667ab Vladyslav Bondarenko 2025-02-02 00:04:55
fix: show auras over role widgets 3bb62c88147af0ee522f4ce963ce206c315f4c9a Vladyslav Bondarenko 2025-02-01 21:27:33
Commit f34c334ca838ca8c26106f89fa7e088bf74af36b - feat!: integrate party pets frame
Add dynamic pets frame to party frame.

Additionally, document the pets frame template.
Author: Vladyslav Bondarenko
Author date (UTC): 2025-02-09 22:59
Committer name: Vladyslav Bondarenko
Committer date (UTC): 2025-02-09 22:59
Parent(s): b7e195cf9623c0e7280a2a76d34de2f078373852
Signer:
Signing key: EFF9624877D25D02
Signing status: E
Tree: 918b6ecd02f530272ab51a420cad336c1ec739ff
File Lines added Lines deleted
src/ChorusPartyFrame.xml 64 44
src/ChorusPetFrameTemplate.lua 194 27
src/ChorusPetFrameTemplate.xml 31 4
File src/ChorusPartyFrame.xml changed (mode: 100644) (index 74d49aa..b73ed35)
12 12 </Frame> </Frame>
13 13 </Frames> </Frames>
14 14 </Frame> </Frame>
15 <Frame name="ChorusPartyPetUnitFrameTemplate" inherits="ChorusTinyUnitFrameTemplate,ChorusMemberUnitFrameTemplate" virtual="true"/>
16 15 <Frame name="ChorusPartyTOTUnitFrameTemplate" inherits="ChorusTinyUnitFrameTemplate,ChorusTOTUnitFrameTemplate" virtual="true"/> <Frame name="ChorusPartyTOTUnitFrameTemplate" inherits="ChorusTinyUnitFrameTemplate,ChorusTOTUnitFrameTemplate" virtual="true"/>
17 <Frame name="ChorusPartyMemberFrameTemplate" protected="false" virtual="true">
18 <Size>
19 <AbsDimension x="255" y="150"/>
20 </Size>
21 <Frames>
22 <Frame name="$parentUnitFrame" inherits="ChorusPartyUnitFrameTemplate">
23 <Anchors>
24 <Anchor point="CENTER">
25 <Offset x="0" y="0"/>
26 </Anchor>
27 </Anchors>
28 </Frame>
29 <Frame name="$parentTargetFrame" inherits="ChorusPartyTOTUnitFrameTemplate">
30 <Anchors>
31 <Anchor point="BOTTOMLEFT" relativeTo="$parentUnitFrame" relativePoint="BOTTOMRIGHT">
32 <Offset x="12" y="60"/>
33 </Anchor>
34 </Anchors>
35 </Frame>
36 <Frame name="$parentPetFrame" inherits="ChorusPartyPetUnitFrameTemplate">
37 <Anchors>
38 <Anchor point="BOTTOMLEFT" relativeTo="$parentUnitFrame" relativePoint="BOTTOMRIGHT">
39 <Offset x="12" y="30"/>
40 </Anchor>
41 </Anchors>
42 </Frame>
43 </Frames>
44 <Scripts>
45 <OnLoad>Chorus.partyMemberFrameMain(self);</OnLoad>
46 </Scripts>
47 </Frame>
48 16 <Frame name="ChorusPartyFrame"> <Frame name="ChorusPartyFrame">
49 17 <Size> <Size>
50 <AbsDimension x="255" y="600"/>
18 <AbsDimension x="650" y="140"/>
51 19 </Size> </Size>
52 20 <Anchors> <Anchors>
53 21 <Anchor point="TOPLEFT"> <Anchor point="TOPLEFT">
 
62 30 </Layer> </Layer>
63 31 </Layers> </Layers>
64 32 <Frames> <Frames>
65 <Frame name="ChorusPartyMemberFrame1" inherits="ChorusPartyMemberFrameTemplate" id="1">
33 <!-- party1 -->
34 <Frame name="ChorusPartyUnitFrame1" inherits="ChorusPartyUnitFrameTemplate" id="1">
66 35 <Anchors> <Anchors>
67 <Anchor point="TOPRIGHT">
36 <Anchor point="BOTTOMLEFT">
68 37 <Offset x="0" y="0"/> <Offset x="0" y="0"/>
69 38 </Anchor> </Anchor>
70 39 </Anchors> </Anchors>
 
72 41 <Attribute name="unit" type="string" value="party1"/> <Attribute name="unit" type="string" value="party1"/>
73 42 </Attributes> </Attributes>
74 43 </Frame> </Frame>
75 <Frame name="ChorusPartyMemberFrame2" inherits="ChorusPartyMemberFrameTemplate" id="2">
44 <Frame name="ChorusPartyUnitFrame1TargetFrame" inherits="ChorusPartyTOTUnitFrameTemplate">
76 45 <Anchors> <Anchors>
77 <Anchor point="TOPRIGHT" relativeTo="ChorusPartyMemberFrame1" relativePoint="BOTTOMRIGHT">
78 <Offset x="0" y="0"/>
46 <Anchor point="BOTTOMLEFT" relativeTo="ChorusPartyUnitFrame1" relativePoint="TOPLEFT">
47 <Offset x="48" y="6"/>
48 </Anchor>
49 </Anchors>
50 <Attributes>
51 <Attribute name="unit" type="string" value="party1target"/>
52 </Attributes>
53 </Frame>
54 <!-- party2 -->
55 <Frame name="ChorusPartyUnitFrame2" inherits="ChorusPartyUnitFrameTemplate" id="2">
56 <Anchors>
57 <Anchor point="BOTTOMLEFT">
58 <Offset x="166" y="0"/>
79 59 </Anchor> </Anchor>
80 60 </Anchors> </Anchors>
81 61 <Attributes> <Attributes>
82 62 <Attribute name="unit" type="string" value="party2"/> <Attribute name="unit" type="string" value="party2"/>
83 63 </Attributes> </Attributes>
84 64 </Frame> </Frame>
85 <Frame name="ChorusPartyMemberFrame3" inherits="ChorusPartyMemberFrameTemplate" id="3">
65 <Frame name="ChorusPartyUnitFrame2TargetFrame" inherits="ChorusPartyTOTUnitFrameTemplate">
86 66 <Anchors> <Anchors>
87 <Anchor point="TOPRIGHT" relativeTo="ChorusPartyMemberFrame2" relativePoint="BOTTOMRIGHT">
88 <Offset x="0" y="0"/>
67 <Anchor point="BOTTOMLEFT" relativeTo="ChorusPartyUnitFrame2" relativePoint="TOPLEFT">
68 <Offset x="48" y="6"/>
69 </Anchor>
70 </Anchors>
71 <Attributes>
72 <Attribute name="unit" type="string" value="party2target"/>
73 </Attributes>
74 </Frame>
75 <!-- party3 -->
76 <Frame name="ChorusPartyUnitFrame3" inherits="ChorusPartyUnitFrameTemplate" id="3">
77 <Anchors>
78 <Anchor point="BOTTOMLEFT">
79 <Offset x="332" y="0"/>
89 80 </Anchor> </Anchor>
90 81 </Anchors> </Anchors>
91 82 <Attributes> <Attributes>
92 83 <Attribute name="unit" type="string" value="party3"/> <Attribute name="unit" type="string" value="party3"/>
93 84 </Attributes> </Attributes>
94 85 </Frame> </Frame>
95 <Frame name="ChorusPartyMemberFrame4" inherits="ChorusPartyMemberFrameTemplate" id="4">
86 <Frame name="ChorusPartyUnitFrame3TargetFrame" inherits="ChorusPartyTOTUnitFrameTemplate">
96 87 <Anchors> <Anchors>
97 <Anchor point="TOPRIGHT" relativeTo="ChorusPartyMemberFrame3" relativePoint="BOTTOMRIGHT">
98 <Offset x="0" y="0"/>
88 <Anchor point="BOTTOMLEFT" relativeTo="ChorusPartyUnitFrame3" relativePoint="TOPLEFT">
89 <Offset x="48" y="6"/>
90 </Anchor>
91 </Anchors>
92 <Attributes>
93 <Attribute name="unit" type="string" value="party3target"/>
94 </Attributes>
95 </Frame>
96 <!-- party4 -->
97 <Frame name="ChorusPartyUnitFrame4" inherits="ChorusPartyUnitFrameTemplate" id="4">
98 <Anchors>
99 <Anchor point="BOTTOMLEFT">
100 <Offset x="489" y="0"/>
99 101 </Anchor> </Anchor>
100 102 </Anchors> </Anchors>
101 103 <Attributes> <Attributes>
102 104 <Attribute name="unit" type="string" value="party4"/> <Attribute name="unit" type="string" value="party4"/>
103 105 </Attributes> </Attributes>
104 106 </Frame> </Frame>
107 <Frame name="ChorusPartyUnitFrame4TargetFrame" inherits="ChorusPartyTOTUnitFrameTemplate">
108 <Anchors>
109 <Anchor point="BOTTOMLEFT" relativeTo="ChorusPartyUnitFrame4" relativePoint="TOPLEFT">
110 <Offset x="48" y="6"/>
111 </Anchor>
112 </Anchors>
113 <Attributes>
114 <Attribute name="unit" type="string" value="party4target"/>
115 </Attributes>
116 </Frame>
117 <!-- Pets for every member. -->
118 <Frame name="ChorusPartyPetFrame" inherits="ChorusPartyPetFrameTemplate">
119 <Anchors>
120 <Anchor point="TOPLEFT" relativeTo="ChorusPartyFrame" relativePoint="BOTTOMLEFT">
121 <Offset x="6" y="-6"/>
122 </Anchor>
123 </Anchors>
124 </Frame>
105 125 </Frames> </Frames>
106 126 <Scripts> <Scripts>
107 127 <OnLoad>Chorus.partyFrameMain(self);</OnLoad> <OnLoad>Chorus.partyFrameMain(self);</OnLoad>
File src/ChorusPetFrameTemplate.lua changed (mode: 100644) (index f28660d..0ab3a77)
1 --[[--
2 @submodule chorus
3 ]]
4
1 5 local Chorus = Chorus local Chorus = Chorus
2 local ChorusPetFrameSecureHandler = ChorusPetFrameSecureHandler
3 6
4 7 local strtrim = strtrim local strtrim = strtrim
5 8
 
... ... local CreateFrame = CreateFrame
7 10
8 11 local RegisterStateDriver = RegisterStateDriver local RegisterStateDriver = RegisterStateDriver
9 12
13 --[[--
14 Make given unit button behave like a pet button that belongs in pets frame.
15
16 WARNING: The argument pet button `b` must have it's property `unit` set to
17 a valid value, like `raidpet13` or `party3pet`.
18
19 First, register a state driver for the button. A state driver evaluates a given
20 macro at real time, and then changes secure frame properties according with
21 results. (A macro in this context is a subset of domain-specific language (DSL)
22 peculiar to World of Warcraft.)
23
24 Given corresponding pet exists, set property `state-unitexists` to `1`, and to
25 `0` otherwise.
26
27 Second, register a secure listener, that will run every time the
28 `state-unitexists` property changes. This listener will run the secure script
29 snippet, argument `secureScriptBody`, every time the property changes.
30
31 The secure script that is expected is exact and cannot be substituted without
32 chaning every other part of the program.
33
34 The purpose of the secure script is to hide absent pets, show present pets, and
35 layout present pets neatly.
36
37 @see petFrameMain
38 @see getSecureScriptBody
39
40 @see FrameXML/SecureStateDriver.lua:function RegisterStateDriver
41 @see FrameXML/SecureHandlers.lua:function SecureHandlerWrapScript
42
43 @function petButtonInit
44 @tparam frame b this protected pet button
45 @tparam frame secureHandler secure handler that will execute the secure script body for every pet button when appropriate
46 @tparam string secureScriptBody the secure script that will be executed every time pets are added or removed from player group
47 @return nothing, only produces side effects
48 ]]
49 local function petButtonInit(b, secureHandler, secureScriptBody)
50 assert(b ~= nil)
51 assert(b:IsProtected())
52
53 assert(secureHandler ~= nil)
54
55 assert(secureScriptBody ~= nil)
56 assert('string' == type(secureScriptBody))
57
58 local u = b:GetAttribute('unit')
59 assert(u ~= nil)
60 assert('string' == type(u))
61 u = strtrim(u)
62 assert(string.len(u) >= 1)
63 assert(string.len(u) <= 256)
64
65 local secureCmd = string.format('[@%s,exists] 1; [@%s,noexists] 0;', u, u)
66 RegisterStateDriver(b, 'unitexists', secureCmd)
67
68 secureHandler:WrapScript(b, 'OnAttributeChanged', secureScriptBody)
69
70 --[[ The pet frame is duplicated for every raid profile.
71 Make sure the buttons are hidden, given the raid profile is
72 hidden. ]]--
73
74 UnregisterUnitWatch(b)
75 b:Hide()
76 end
77
78 --[[--
79 Create forty pet buttons for the given pet frame to represent any pet in a raid group.
80
81 @see petButtonInit
82
83 @function petButtonFactory
84 @tparam frame petFrame this pets frame that will hold pet buttons created by this function
85 @tparam string petButtonTemplate optional frame template for the pet button, defaults to `ChorusPetButtonTemplate`
86 @tparam frame secureHandler secure handler that will execute the secure script body for every pet button when appropriate
87 @tparam string secureScriptBody the secure script that will be executed every time pets are added or removed from player group
88 @return nothing, only produces side effects
89 ]]
10 90 local function petButtonFactory(petFrame, petButtonTemplate, secureHandler, secureScriptBody) local function petButtonFactory(petFrame, petButtonTemplate, secureHandler, secureScriptBody)
11 91 assert(petFrame ~= nil) assert(petFrame ~= nil)
12 92
 
... ... local function petButtonFactory(petFrame, petButtonTemplate, secureHandler, secu
38 118
39 119 while(i < MAX_RAID_MEMBERS) do while(i < MAX_RAID_MEMBERS) do
40 120 i = i + 1 i = i + 1
41 local n = string.format('%s%02d', m, i)
121 local n = string.format('%sPetButton%02d', m, i)
42 122 local b = _G[n] or CreateFrame('FRAME', n, petFrame, petButtonTemplate) local b = _G[n] or CreateFrame('FRAME', n, petFrame, petButtonTemplate)
43 123
44 124 local u = 'raidpet' .. tostring(i) local u = 'raidpet' .. tostring(i)
45 125 b:SetAttribute('unit', u) b:SetAttribute('unit', u)
46 126 b:SetID(i) b:SetID(i)
47 127
48 assert(b:IsProtected())
49
50 local secureCmd = string.format('[@%s,exists] 1; [@%s,noexists] 0;', u, u)
51 RegisterStateDriver(b, 'unitexists', secureCmd)
52
53 secureHandler:WrapScript(b, 'OnAttributeChanged', secureScriptBody)
54
55 --[[ The pet frame is duplicated for every raid profile.
56 Make sure the buttons are hidden, given the raid profile is
57 hidden. ]]--
58
59 UnregisterUnitWatch(b)
60 b:Hide()
128 petButtonInit(b, secureHandler, secureScriptBody)
61 129 end end
62 130 end end
63 131
64 function Chorus.petFrameMain(petFrame)
65 assert(petFrame ~= nil)
132 --[[--
133 Returns a script snippet presented as a string to be compiled at runtime.
66 134
67 petFrame:RegisterEvent('PARTY_CONVERTED_TO_RAID')
68 petFrame:RegisterEvent('PARTY_MEMBERS_CHANGED')
69 petFrame:RegisterEvent('RAID_ROSTER_UPDATE')
70 petFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
135 This script is intended to be executed by secure handlers, either explicitly or
136 as reaction to a property change.
71 137
72 local secureHandler = ChorusPetFrameSecureHandler
73 secureHandler:SetFrameRef('ChorusPetFrame', petFrame)
138 This script is wrapped over every pet button. When run, the script finds the
139 group pets frame, using `GetFrameRef` mechanism. Then, it iterates over every
140 button and changes it appropriately to the game state.
74 141
75 --[[-- @fixme State driver cannot correctly determine when raid pets change.
76 Wrap state listener for buttons instead.
77 ]]
142 @see petButtonInit
78 143
144 @see FrameXML/SecureHandlers.lua:function SecureHandlerGetFrameRef
145 @see FrameXML/RestrictedFrames.lua:SetPoint
146 @see FrameXML/RestrictedEnvironment.lua:UnitExists
147
148 @function getSecureScriptBody
149 @treturn string the script snippet body used by secure handlers
150 ]]
151 local function getSecureScriptBody()
79 152 --[[-- @fixme Replace hardcoded button dimensions. --[[-- @fixme Replace hardcoded button dimensions.
80 153 ]] ]]
81 154
82 local secureScriptBody = [[
155 return [[
83 156 -- When attribute changed, given it was not 'unitexists', exit. -- When attribute changed, given it was not 'unitexists', exit.
84 157 -- When script executed explicitly, ignore the check and continue. -- When script executed explicitly, ignore the check and continue.
85 158 -- WARNING: Filtering by attribute change is required. Otherwise it may crash the game. -- WARNING: Filtering by attribute change is required. Otherwise it may crash the game.
 
... ... function Chorus.petFrameMain(petFrame)
132 205 petFrame:SetHeight(buttonHeight * (row + 1)) petFrame:SetHeight(buttonHeight * (row + 1))
133 206 petFrame:SetWidth(buttonWidth * 5) petFrame:SetWidth(buttonWidth * 5)
134 207 ]] ]]
208 end
209
210 --[[--
211 Initialize pets frame, to dynamically display player combat pets in player
212 groups to the user.
213
214 It is difficult to predict how many combat pets there will be in any specific
215 player group. Hence, the position of pet buttons is calculated dynamically at
216 runtime, instead of set manually.
135 217
218 There is an additional complication. Pet buttons are restricted (protected,
219 secure) frames. Restricted frames cannot be manipulated in combat. Therefore, a
220 secure handler mechanism is used instead of usual Lua scripts, to calculate pet
221 button position and visibility at runtime.
222
223 There are two main profiles for the pet frame, raid and party. Raid pets frame
224 allocates pet buttons dynamically with Lua script. Party pets frame defines pet
225 buttons explicitly with FrameXML DSL.
226
227 This initialization function is run for both profiles. In addition there are
228 profile specific initialization steps defined elsewhere.
229
230 @see petRaidFrameMain
231 @see petPartyFrameMain
232
233 @see FrameXML/SecureHandlers.lua:function SecureHandlerSetFrameRef
234
235 @function petFrameMain
236 @tparam frame petFrame this pet frame that holds pet buttons
237 @return nothing, only produces side effects
238 ]]
239 local function petFrameMain(petFrame)
240 assert(petFrame ~= nil)
241
242 local secureHandler = _G[petFrame:GetName() .. 'SecureHandler']
243 assert(secureHandler ~= nil)
244 secureHandler:SetFrameRef('ChorusPetFrame', petFrame)
245 end
246
247 --[[--
248 Initialize pet buttons for any raid profile frame.
249
250 This function will allocate pet buttons at runtime on load, then initialize
251 them.
252
253 @see petFrameMain
254 @see petButtonFactory
255
256 @see FrameXML/SecureHandlers.lua:function SecureHandlerWrapScript
257
258 @function petRaidFrameMain
259 @tparam frame petFrame this pets frame
260 @return nothing, only produces side effects
261 ]]
262 function Chorus.petRaidFrameMain(petFrame)
263 petFrameMain(petFrame)
264
265 local secureHandler = _G[petFrame:GetName() .. 'SecureHandler']
266 assert(secureHandler ~= nil)
267
268 local secureScriptBody = getSecureScriptBody()
136 269 petButtonFactory(petFrame, 'ChorusPetButtonTemplate', secureHandler, secureScriptBody) petButtonFactory(petFrame, 'ChorusPetButtonTemplate', secureHandler, secureScriptBody)
137 270
138 271 --[[ Initialize frames at login. Only works out of combat. ]]-- --[[ Initialize frames at login. Only works out of combat. ]]--
139 272 secureHandler:Execute(secureScriptBody) secureHandler:Execute(secureScriptBody)
140 273 end end
274
275 --[[--
276 Initialize pet buttons for `ChorusPartyPetFrameTemplate`.
277
278 Unlike raid pets frame, this function does not allocate frames dynamically.
279 Instead, it initializes frames defined by FrameXML.
280
281 @see petFrameMain
282
283 @see FrameXML/SecureHandlers.lua:function SecureHandlerWrapScript
284
285 @function petPartyFrameMain
286 @tparam frame petFrame this pets frame
287 @return nothing, only produces side effects
288 ]]
289 function Chorus.petPartyFrameMain(petFrame)
290 petFrameMain(petFrame)
291
292 local secureHandler = _G[petFrame:GetName() .. 'SecureHandler']
293 assert(secureHandler ~= nil)
294
295 local secureScriptBody = getSecureScriptBody()
296
297 local t = {petFrame:GetChildren()}
298 local i = 0
299 while(i < #t) do
300 i = i + 1
301 local b = t[i]
302 petButtonInit(b, secureHandler, secureScriptBody)
303 end
304
305 --[[ Initialize frames at login. Only works out of combat. ]]--
306 secureHandler:Execute(secureScriptBody)
307 end
File src/ChorusPetFrameTemplate.xml changed (mode: 100644) (index af2c2c5..d6fcbea)
1 1 <?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
2 2 <Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/">
3 <Frame name="ChorusPetFrameSecureHandler" inherits="SecureHandlerStateTemplate"/>
4 3 <Script file="ChorusPetFrameTemplate.lua"/> <Script file="ChorusPetFrameTemplate.lua"/>
5 4 <Frame name="ChorusPetButtonTemplate" inherits="ChorusTinyUnitFrameTemplate,ChorusMemberUnitFrameTemplate" virtual="true" protected="true"> <Frame name="ChorusPetButtonTemplate" inherits="ChorusTinyUnitFrameTemplate,ChorusMemberUnitFrameTemplate" virtual="true" protected="true">
6 5 </Frame> </Frame>
 
8 7 <Size> <Size>
9 8 <AbsDimension x="320" y="128"/> <AbsDimension x="320" y="128"/>
10 9 </Size> </Size>
10 <Frames>
11 <Frame name="$parentSecureHandler" inherits="SecureHandlerStateTemplate"/>
12 </Frames>
11 13 <Layers> <Layers>
12 14 <Layer level="BACKGROUND"> <Layer level="BACKGROUND">
13 15 <Texture name="$parentBackground" setAllPoints="true" hidden="true"> <Texture name="$parentBackground" setAllPoints="true" hidden="true">
 
15 17 </Texture> </Texture>
16 18 </Layer> </Layer>
17 19 </Layers> </Layers>
18 <Scripts>
19 <OnLoad>Chorus.petFrameMain(self);</OnLoad>
20 </Scripts>
21 20 </Frame> </Frame>
22 21 <Frame name="ChorusRaidPetFrameTemplate" inherits="ChorusPetFrameTemplate" virtual="true"> <Frame name="ChorusRaidPetFrameTemplate" inherits="ChorusPetFrameTemplate" virtual="true">
22 <Scripts>
23 <OnLoad>Chorus.petRaidFrameMain(self);</OnLoad>
24 </Scripts>
23 25 </Frame> </Frame>
24 26 <Frame name="ChorusPartyPetFrameTemplate" inherits="ChorusPetFrameTemplate" virtual="true"> <Frame name="ChorusPartyPetFrameTemplate" inherits="ChorusPetFrameTemplate" virtual="true">
27 <Frames>
28 <Frame name="$parentPetButton1" inherits="ChorusPetButtonTemplate" id="1">
29 <Attributes>
30 <Attribute name="unit" type="string" value="party1pet"/>
31 </Attributes>
32 </Frame>
33 <Frame name="$parentPetButton2" inherits="ChorusPetButtonTemplate" id="2">
34 <Attributes>
35 <Attribute name="unit" type="string" value="party2pet"/>
36 </Attributes>
37 </Frame>
38 <Frame name="$parentPetButton3" inherits="ChorusPetButtonTemplate" id="3">
39 <Attributes>
40 <Attribute name="unit" type="string" value="party3pet"/>
41 </Attributes>
42 </Frame>
43 <Frame name="$parentPetButton4" inherits="ChorusPetButtonTemplate" id="4">
44 <Attributes>
45 <Attribute name="unit" type="string" value="party4pet"/>
46 </Attributes>
47 </Frame>
48 </Frames>
49 <Scripts>
50 <OnLoad>Chorus.petPartyFrameMain(self);</OnLoad>
51 </Scripts>
25 52 </Frame> </Frame>
26 53 </Ui> </Ui>
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/vrtc/chorus

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/vrtc/chorus

Clone this repository using git:
git clone git://git.rocketgit.com/user/vrtc/chorus

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main