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)
fix: single frame toggles every group frame 44d20820afb80aa381c2cfb1272123ba9a8e6156 Vladyslav Bondarenko 2024-01-24 18:47:12
build: migrate to make and adoc 1e410bff214b6a32cd13343d3b7e521afa0cf93f Vladyslav Bondarenko 2024-01-23 14:42:21
doc: note the need to backport GetSpellName 8dac49bb037de94b2980a45b91152691d9c5b98b Vladyslav Bondarenko 2024-01-23 14:24:44
feat: show remaining aura charges beedf659895a3ecdd0df97e14e63d87f534d0bbc Vladyslav Bondarenko 2024-01-23 14:24:01
fix: remove aura button overlay and artwork gap d0785edceabe16095e6e56aa42d88fb25bca3eb7 Vladyslav Bondarenko 2024-01-21 22:35:02
Release 0.6 d76ca463e13d1a47b68541f33faa9c44ec745347 Vladyslav Bondarenko 2023-09-12 02:02:46
fix!: Show arena as party 1c7d9c4c80948486eacd0c0eaa8f785a1efaa5ae Vladyslav Bondarenko 2023-09-11 23:51:47
fix: Filter out aura events 193d8864ae6ca3a2f6bf3e6ed2260e06722e47fc Vladyslav Bondarenko 2023-09-11 21:14:26
feat: Arrange all solo frames in one column 5d1f55b456efee534b970ed3ec80c5aeb334baa8 Vladyslav Bondarenko 2023-09-11 19:31:46
fix!: Show arena as party 6b1ac51958c213e1e06ef4c43b2e01a7ef0d1e01 Vladyslav Bondarenko 2023-09-11 17:06:51
feat: Add arrow graphics to aura tooltip button 16b016797a6bc7bb65d5cab8caa7dc8beeb4b48d Vladyslav Bondarenko 2023-09-11 16:35:40
feat: Add arrow graphics to aura tooltip button 12129625fc1277c77974cc9a2b63b3cfc592cdf6 Vladyslav Bondarenko 2023-09-11 16:35:40
fix: Improve small raid layout a4e48cb4e4b198d141abd4ce3914e71f5155f502 Vladyslav Bondarenko 2023-09-07 06:55:19
fix!: Simplify aura sorting algorithm a2a294f60cee50ab51d044139f50d784bb8f3455 Vladyslav Bondarenko 2023-09-07 01:49:15
feat!: Add raid frame with 25 small buttons 5bdc57423adeb4137bc796932657cf64f22ef8ad Vladyslav Bondarenko 2023-09-01 01:12:15
feat!: Add UnitSetRole backport 1eb6a3777cb6361f57386959cdec4066715bb0a6 Vladyslav Bondarenko 2023-08-31 18:07:35
feat(build): Add separation for Cata and Wrath API c1ec823b22648324afb48852149296f6b0612830 Vladyslav Bondarenko 2023-08-31 18:05:42
feat!: Release 0.5 ff0038bc36df311a01b038e192c3e6b495e5c509 Vladyslav Bondarenko 2023-08-30 23:45:43
fix!: Remove old flavour of unit frames 58d82ae1ba66bfc0acf41b97df99746a57a7a7cd Vladyslav Bondarenko 2023-08-30 23:38:49
fix: Update solo tot frames 4204e7a2649b970d28f4b0f38f4dc60e90cd40d0 Vladyslav Bondarenko 2023-08-30 23:37:37
Commit 44d20820afb80aa381c2cfb1272123ba9a8e6156 - fix: single frame toggles every group frame
Previously, every raid or party frame handled their visibility
themselves. This resulted in unpredictable behaviour when any changes
were introduced. This commit changes the implementation, to where all
group frame toggling is handled by `ChorusGroupFrame`. It depends on all
other frame existing and initialized prior.

Additionally, fix minor issues that the static analysis complained
about.
Author: Vladyslav Bondarenko
Author date (UTC): 2024-01-24 18:47
Committer name: Vladyslav Bondarenko
Committer date (UTC): 2024-01-24 18:47
Parent(s): 4c85344d79122bc7ff86d5c267058499b6c65ba7
Signer:
Signing key: EFF9624877D25D02
Signing status: E
Tree: f204fb0f947a6024d1cf8aaf49d305254d212a54
File Lines added Lines deleted
etc/luacheckrc.lua 7 0
src/Chorus.xml 3 0
src/ChorusGroupFrame.lua 49 0
src/ChorusGroupFrame.xml 19 0
src/ChorusPartyFrame.lua 46 55
src/ChorusPartyFrame.xml 3 0
src/ChorusRaidFrame.lua 0 32
File etc/luacheckrc.lua changed (mode: 100644) (index 1262875..3340081)
... ... stds.framexml = {
150 150
151 151 stds.chorus = { stds.chorus = {
152 152 read_globals = { read_globals = {
153 'ChorusFocusFrame',
154 'ChorusFrame',
155 'ChorusGroupFrame',
156 'ChorusPartyFrame',
157 'ChorusPlayerFrame',
158 'ChorusRaidFrame',
159 'ChorusTargetFrame',
153 160 }, },
154 161 globals = { globals = {
155 162 --[[ TODO Add script that populates created frames at runtime --[[ TODO Add script that populates created frames at runtime
File src/Chorus.xml changed (mode: 100644) (index f48f721..bdcba4f)
6 6 Configuration is done in the snippet itself. --> Configuration is done in the snippet itself. -->
7 7 <Script file="ChorusTest.lua"/> <Script file="ChorusTest.lua"/>
8 8 <Include file="ChorusFont.xml"/> <Include file="ChorusFont.xml"/>
9 <!-- Templates (abstract classes). -->
9 10 <Include file="ChorusAuraButtonTemplate.xml"/> <Include file="ChorusAuraButtonTemplate.xml"/>
10 11 <Include file="ChorusAuraFrameTemplate.xml"/> <Include file="ChorusAuraFrameTemplate.xml"/>
11 12 <Include file="ChorusAuraTooltipFrameTemplate.xml"/> <Include file="ChorusAuraTooltipFrameTemplate.xml"/>
 
26 27 <Include file="ChorusLargeUnitFrameTemplate.xml"/> <Include file="ChorusLargeUnitFrameTemplate.xml"/>
27 28 <Include file="ChorusSmallUnitFrameTemplate.xml"/> <Include file="ChorusSmallUnitFrameTemplate.xml"/>
28 29 <Include file="ChorusTinyUnitFrameTemplate.xml"/> <Include file="ChorusTinyUnitFrameTemplate.xml"/>
30 <!-- Frames (concrete classes, interface implementations, object instances). -->
29 31 <Include file="ChorusPartyFrame.xml"/> <Include file="ChorusPartyFrame.xml"/>
30 32 <Include file="ChorusRaidFrame.xml"/> <Include file="ChorusRaidFrame.xml"/>
33 <Include file="ChorusGroupFrame.xml"/>
31 34 <Include file="ChorusPlayerFrame.xml"/> <Include file="ChorusPlayerFrame.xml"/>
32 35 <Include file="ChorusTargetFrame.xml"/> <Include file="ChorusTargetFrame.xml"/>
33 36 <Include file="ChorusFocusFrame.xml"/> <Include file="ChorusFocusFrame.xml"/>
File src/ChorusGroupFrame.lua added (mode: 100644) (index 0000000..1eec3bd)
1 local GetNumPartyMembers = Chorus.test.GetNumPartyMembers or GetNumPartyMembers
2 local UnitInParty = Chorus.test.UnitInParty or UnitInParty
3 local UnitInRaid = Chorus.test.UnitInRaid or UnitInRaid
4
5 local Chorus = Chorus
6 local ChorusPartyFrame = ChorusPartyFrame
7 local ChorusRaidFrame = ChorusRaidFrame
8
9 local function groupFrameEventProcessor(self)
10 assert(self ~= nil)
11
12 if IsActiveBattlefieldArena() then
13 --[[ TODO Implement separate or additional arena unit group frame. ]]--
14 self:Show()
15 ChorusPartyFrame:Show()
16 ChorusRaidFrame:Hide()
17 elseif UnitInRaid('player') then
18 self:Show()
19 ChorusPartyFrame:Hide()
20 --[[ TODO Implement separate raid profiles for 10, 25 and 40 men raids. ]]--
21 ChorusRaidFrame:Show()
22 elseif UnitInParty('player') and GetNumPartyMembers() >= 1 then
23 self:Show()
24 ChorusPartyFrame:Show()
25 ChorusRaidFrame:Hide()
26 else
27 self:Hide()
28 ChorusPartyFrame:Hide()
29 ChorusRaidFrame:Hide()
30 end
31 end
32
33 function Chorus.groupFrameMain(self)
34 assert(self ~= nil)
35
36 self:SetScript('OnEvent', groupFrameEventProcessor)
37
38 self:RegisterEvent('BATTLEFIELDS_CLOSED');
39 self:RegisterEvent('BATTLEFIELDS_SHOW');
40 self:RegisterEvent('PARTY_CONVERTED_TO_RAID')
41 self:RegisterEvent('PARTY_LEADER_CHANGED');
42 self:RegisterEvent('PARTY_MEMBERS_CHANGED')
43 self:RegisterEvent('PARTY_MEMBER_DISABLE')
44 self:RegisterEvent('PARTY_MEMBER_ENABLE')
45 self:RegisterEvent('PLAYER_ALIVE');
46 self:RegisterEvent('PLAYER_LOGIN')
47 self:RegisterEvent('RAID_ROSTER_UPDATE')
48 self:RegisterEvent('UPDATE_BATTLEFIELD_STATUS');
49 end
File src/ChorusGroupFrame.xml added (mode: 100644) (index 0000000..79fdabd)
1 <?xml version="1.0" encoding="UTF-8"?>
2 <Ui xmlns="http://www.blizzard.com/wow/ui/">
3 <Script file="ChorusGroupFrame.lua"/>
4 <Frame name="ChorusGroupFrame" hidden="true">
5 <Size>
6 <AbsDimension x="800" y="600"/>
7 </Size>
8 <Anchors>
9 <Anchor point="CENTER">
10 <Offset>
11 <AbsDimension x="0" y="0"/>
12 </Offset>
13 </Anchor>
14 </Anchors>
15 <Scripts>
16 <OnLoad>Chorus.groupFrameMain(self);</OnLoad>
17 </Scripts>
18 </Frame>
19 </Ui>
File src/ChorusPartyFrame.lua changed (mode: 100644) (index 55ea6f9..5f0bd9a)
1 local SecureButton_GetUnit = SecureButton_GetUnit
2
1 3 local Chorus = Chorus local Chorus = Chorus
2 4
3 local GetNumPartyMembers = Chorus.test.GetNumPartyMembers or GetNumPartyMembers
4 local UnitInParty = Chorus.test.UnitInParty or UnitInParty
5 local UnitInRaid = Chorus.test.UnitInRaid or UnitInRaid
5 --[[--
6 Given valid player unit designation, infer from it corresponding pet and target unit designations.
6 7
7 local function partyFrameEventProcessor(self)
8 assert(self ~= nil)
8 Does not check if unit exists.
9 Used in party frame initialization.
9 10
10 if IsActiveBattlefieldArena() then
11 self:Show()
12 return
13 end
14 if UnitInRaid('player') then
15 self:Hide()
16 elseif UnitInParty('player') and GetNumPartyMembers() >= 1 then
17 self:Show()
18 else
19 self:Hide()
20 end
21 end
11 @function mapUnitDesignation
12
13 @tparam string unitDesignation unit designation in the same format as native
14 unit functions, specifically party, arena or raid members (party3, raid13,
15 arena2)
16
17 @treturn string sanitized given unit designation, for example party3
18
19 @treturn string given unit pet designation, for example partypet3
22 20
21 @treturn string given unit target designation, for example party3target
22 ]]
23 23 local function mapUnitDesignation(unitDesignation) local function mapUnitDesignation(unitDesignation)
24 24 assert(unitDesignation ~= nil) assert(unitDesignation ~= nil)
25 25
26 26 if 'player' == unitDesignation then if 'player' == unitDesignation then
27 27 return 'player', 'pet', 'target' return 'player', 'pet', 'target'
28 elseif 'party1' == unitDesignation then
29 return 'party1', 'partypet1', 'party1target'
30 elseif 'party2' == unitDesignation then
31 return 'party2', 'partypet2', 'party2target'
32 elseif 'party3' == unitDesignation then
33 return 'party3', 'partypet3', 'party3target'
34 elseif 'party4' == unitDesignation then
35 return 'party4', 'partypet4', 'party4target'
28 elseif string.match(unitDesignation, 'raid') then
29 local raidUnit = string.match(unitDesignation, 'raid%d+')
30 local raidPet = 'raidpet' .. string.match(unitDesignation, 'raid(%d+)')
31 local raidTarget = 'raid' .. string.match(unitDesignation, 'raid(%d+)') .. 'target'
32 return raidUnit, raidPet, raidTarget
33 elseif string.match(unitDesignation, 'party') then
34 local partyUnit = string.match(unitDesignation, 'party%d+')
35 local partyPet = 'partypet' .. string.match(unitDesignation, 'party(%d+)')
36 local partyTarget = 'party' .. string.match(unitDesignation, 'party(%d+)') .. 'target'
37 return partyUnit, partyPet, partyTarget
38 elseif string.match(unitDesignation, 'arena') then
39 local arenaUnit = string.match(unitDesignation, 'arena%d+')
40 local arenaPet = 'arenapet' .. string.match(unitDesignation, 'arena(%d+)')
41 local arenaTarget = 'arena' .. string.match(unitDesignation, 'arena(%d+)') .. 'target'
42 return arenaUnit, arenaPet, arenaTarget
36 43 else else
37 error('unexpected value: expect at most four party members excluding player')
44 error('invalid argument: must be a unit designation of a player character or a group member')
38 45 end end
39 46 end end
40 47
41 local function initPartyMemberFrame(partyMemberFrame)
48 local function partyMemberFrameInit(partyMemberFrame)
42 49 assert(partyMemberFrame ~= nil) assert(partyMemberFrame ~= nil)
43 50
44 51 local n = partyMemberFrame:GetName() local n = partyMemberFrame:GetName()
45 52 assert(n ~= nil) assert(n ~= nil)
46 53
47 54 local u = partyMemberFrame:GetAttribute('unit') local u = partyMemberFrame:GetAttribute('unit')
55
56 if not u then
57 u = SecureButton_GetUnit(partyMemberFrame)
58 end
59
48 60 local _, upet, utarget = mapUnitDesignation(u) local _, upet, utarget = mapUnitDesignation(u)
49 61
50 62 local unitFrame = _G[n .. 'UnitFrame'] local unitFrame = _G[n .. 'UnitFrame']
 
... ... local function initPartyMemberFrame(partyMemberFrame)
59 71 targetFrame:SetAttribute('unit', utarget) targetFrame:SetAttribute('unit', utarget)
60 72 end end
61 73
62 local function partyFrameMain(self)
63 assert(self ~= nil)
64
65 local t = {self:GetChildren()}
66 local i = 0
67 assert(5 == #t, 'invalid state: must be exactly five party member frames')
68 while (i < #t) do
69 i = i + 1
70 local partyMemberFrame = t[i]
71 assert(partyMemberFrame ~= nil)
72
73 initPartyMemberFrame(partyMemberFrame)
74 end
74 function Chorus.partyMemberFrameMain(partyMemberFrame)
75 assert(partyMemberFrame ~= nil)
75 76
76 self:SetScript('OnEvent', partyFrameEventProcessor)
77
78 self:RegisterEvent('BATTLEFIELDS_CLOSED');
79 self:RegisterEvent('BATTLEFIELDS_SHOW');
80 self:RegisterEvent('PARTY_CONVERTED_TO_RAID')
81 self:RegisterEvent('PARTY_LEADER_CHANGED');
82 self:RegisterEvent('PARTY_MEMBERS_CHANGED')
83 self:RegisterEvent('PARTY_MEMBER_DISABLE')
84 self:RegisterEvent('PARTY_MEMBER_ENABLE')
85 self:RegisterEvent('PLAYER_ALIVE');
86 self:RegisterEvent('PLAYER_LOGIN')
87 self:RegisterEvent('RAID_ROSTER_UPDATE')
88 self:RegisterEvent('UPDATE_BATTLEFIELD_STATUS');
77 partyMemberFrame:RegisterEvent('ADDON_LOADED')
78 partyMemberFrame:SetScript('OnEvent', partyMemberFrameInit)
79 partyMemberFrame:SetScript('OnAttributeChanged', partyMemberFrameInit)
89 80 end end
90 81
91 Chorus.partyFrameMain = function(...)
92 return partyFrameMain(...)
82 function Chorus.partyFrameMain(self)
83 assert(self ~= nil)
93 84 end end
File src/ChorusPartyFrame.xml changed (mode: 100644) (index 5cd1563..3e24817)
34 34 <Attributes> <Attributes>
35 35 <Attribute name="unit" type="string" value="none"/> <Attribute name="unit" type="string" value="none"/>
36 36 </Attributes> </Attributes>
37 <Scripts>
38 <OnLoad>Chorus.partyMemberFrameMain(self);</OnLoad>
39 </Scripts>
37 40 </Frame> </Frame>
38 41 <Frame name="ChorusPartyFrame"> <Frame name="ChorusPartyFrame">
39 42 <Size> <Size>
File src/ChorusRaidFrame.lua changed (mode: 100644) (index 0d8d204..8cd7b81)
1 local Chorus = Chorus
2
3 local UnitInRaid = Chorus.test.UnitInRaid or UnitInRaid
4
5 local function raidFrameEventProcessor(self)
6 assert(self ~= nil)
7
8 if UnitInRaid('player') then
9 if not IsActiveBattlefieldArena() then
10 self:Show()
11 else
12 self:Hide()
13 end
14 else
15 self:Hide()
16 end
17 end
18
19 1 local function raidFrameMain(self) local function raidFrameMain(self)
20 2 assert(self ~= nil) assert(self ~= nil)
21
22 self:SetScript('OnEvent', raidFrameEventProcessor)
23
24 self:RegisterEvent('BATTLEFIELDS_CLOSED');
25 self:RegisterEvent('BATTLEFIELDS_SHOW');
26 self:RegisterEvent('PARTY_CONVERTED_TO_RAID')
27 self:RegisterEvent('PARTY_LEADER_CHANGED');
28 self:RegisterEvent('PARTY_MEMBERS_CHANGED')
29 self:RegisterEvent('PARTY_MEMBER_DISABLE')
30 self:RegisterEvent('PARTY_MEMBER_ENABLE')
31 self:RegisterEvent('PLAYER_ALIVE');
32 self:RegisterEvent('PLAYER_LOGIN')
33 self:RegisterEvent('RAID_ROSTER_UPDATE')
34 self:RegisterEvent('UPDATE_BATTLEFIELD_STATUS');
35 3 end end
36 4
37 5 Chorus.raidFrameMain = function(...) Chorus.raidFrameMain = function(...)
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