Subject | Hash | Author | Date (UTC) |
---|---|---|---|
feat!: replace deprecated unit status bars | dd8056c5ba236667f8dd340f8e74e837757bed80 | Vladyslav Bondarenko | 2025-02-26 19:26:47 |
feat!: add new unit health display | 6b2b9d93bdda1f5f8284b37d2bbe21e35387eedd | Vladyslav Bondarenko | 2025-02-26 15:17:19 |
feat: add tiny auras to small unit frame | 835541052fb5452ef35573faf39a5faacc243be3 | Vladyslav Bondarenko | 2025-02-14 18:32:36 |
feat: add chorus slash command | 11427128e833d0f7acaaf720d5fe13746ea95e72 | Vladyslav Bondarenko | 2025-02-12 20:45:56 |
fix: make user configuration frame more robust | f6423c6113559ed00f07a79584e6ef24f78e81d7 | Vladyslav Bondarenko | 2025-02-12 19:51:35 |
feat: prepare release 0.13.0 | adc28078888e57f0f8f221d56ecc297044202b5f | Vladyslav Bondarenko | 2025-02-11 06:36:02 |
fix: remove invisible buttons obstructing clicks | b4701b9c13fbdea44089eae83444e4a24a878a03 | Vladyslav Bondarenko | 2025-02-11 06:30:13 |
fix: position past party member correctly | 91fad9b3decb82a8e289ca38b06a15c25dce19b0 | Vladyslav Bondarenko | 2025-02-10 20:24:23 |
fix: ensure pets party frame loads correctly | 1dd2e348bd15aa642c36057c2f92484755a4cb57 | Vladyslav Bondarenko | 2025-02-09 23:14:40 |
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 |
File conf/make/src.mk changed (mode: 100644) (index c0c90d0..9a6928f) | |||
... | ... | ${srcdir}src/ChorusUnitHealthFrameTemplate.lua \ | |
36 | 36 | ${srcdir}src/ChorusUnitHealthStatusBarTemplate.lua \ | ${srcdir}src/ChorusUnitHealthStatusBarTemplate.lua \ |
37 | 37 | ${srcdir}src/ChorusUnitLevelFrameTemplate.lua \ | ${srcdir}src/ChorusUnitLevelFrameTemplate.lua \ |
38 | 38 | ${srcdir}src/ChorusUnitNameFrameTemplate.lua \ | ${srcdir}src/ChorusUnitNameFrameTemplate.lua \ |
39 | ${srcdir}src/ChorusUnitPowerStatusBarTemplate.lua \ | ||
39 | 40 | ${srcdir}src/local.lua | ${srcdir}src/local.lua |
40 | 41 | ||
41 | 42 | XMLFILES = \ | XMLFILES = \ |
... | ... | ${srcdir}src/ChorusFocusFrame.xml \ | |
51 | 52 | ${srcdir}src/ChorusFont.xml \ | ${srcdir}src/ChorusFont.xml \ |
52 | 53 | ${srcdir}src/ChorusFrame.xml \ | ${srcdir}src/ChorusFrame.xml \ |
53 | 54 | ${srcdir}src/ChorusGroupFrame.xml \ | ${srcdir}src/ChorusGroupFrame.xml \ |
54 | ${srcdir}src/ChorusHealthFrameTemplate.xml \ | ||
55 | 55 | ${srcdir}src/ChorusHugeUnitFrameTemplate.xml \ | ${srcdir}src/ChorusHugeUnitFrameTemplate.xml \ |
56 | 56 | ${srcdir}src/ChorusLargeRaidFrame.xml \ | ${srcdir}src/ChorusLargeRaidFrame.xml \ |
57 | 57 | ${srcdir}src/ChorusLargeUnitFrameTemplate.xml \ | ${srcdir}src/ChorusLargeUnitFrameTemplate.xml \ |
58 | 58 | ${srcdir}src/ChorusPartyFrame.xml \ | ${srcdir}src/ChorusPartyFrame.xml \ |
59 | 59 | ${srcdir}src/ChorusPetFrameTemplate.xml \ | ${srcdir}src/ChorusPetFrameTemplate.xml \ |
60 | 60 | ${srcdir}src/ChorusPlayerFrame.xml \ | ${srcdir}src/ChorusPlayerFrame.xml \ |
61 | ${srcdir}src/ChorusPowerFrameTemplate.xml \ | ||
62 | 61 | ${srcdir}src/ChorusProgressFrameTemplate.xml \ | ${srcdir}src/ChorusProgressFrameTemplate.xml \ |
63 | 62 | ${srcdir}src/ChorusRaidFrameTemplate.xml \ | ${srcdir}src/ChorusRaidFrameTemplate.xml \ |
64 | 63 | ${srcdir}src/ChorusRaidTargetIconFrameTemplate.xml \ | ${srcdir}src/ChorusRaidTargetIconFrameTemplate.xml \ |
... | ... | ${srcdir}src/ChorusUnitGroupRoleFrameTemplate.xml \ | |
80 | 79 | ${srcdir}src/ChorusUnitHealthFrameTemplate.xml \ | ${srcdir}src/ChorusUnitHealthFrameTemplate.xml \ |
81 | 80 | ${srcdir}src/ChorusUnitHealthStatusBarTemplate.xml \ | ${srcdir}src/ChorusUnitHealthStatusBarTemplate.xml \ |
82 | 81 | ${srcdir}src/ChorusUnitLevelFrameTemplate.xml \ | ${srcdir}src/ChorusUnitLevelFrameTemplate.xml \ |
83 | ${srcdir}src/ChorusUnitNameFrameTemplate.xml | ||
82 | ${srcdir}src/ChorusUnitNameFrameTemplate.xml \ | ||
83 | ${srcdir}src/ChorusUnitPowerFrameTemplate.xml \ | ||
84 | ${srcdir}src/ChorusUnitPowerStatusBarTemplate.xml |
File src/Chorus.lua changed (mode: 100644) (index ac8e35a..40194fa) | |||
... | ... | function Chorus.luacheckrcDump() | |
40 | 40 | end | end |
41 | 41 | table.sort(dump) | table.sort(dump) |
42 | 42 | end | end |
43 | |||
44 | local function trace(...) | ||
45 | print(date('%X'), '[Chorus]:', ...) | ||
46 | end | ||
47 | |||
48 | Chorus.trace = function(...) | ||
49 | return trace(...) | ||
50 | end |
File src/Chorus.xml changed (mode: 100644) (index 2d06df2..a88c615) | |||
11 | 11 | <Include file="ChorusAuraTooltipToggleButtonTemplate.xml"/> | <Include file="ChorusAuraTooltipToggleButtonTemplate.xml"/> |
12 | 12 | <Include file="ChorusUnitHealthFrameTemplate.xml"/> | <Include file="ChorusUnitHealthFrameTemplate.xml"/> |
13 | 13 | <Include file="ChorusUnitHealthStatusBarTemplate.xml"/> | <Include file="ChorusUnitHealthStatusBarTemplate.xml"/> |
14 | <!--<Include file="ChorusUnitPowerFrameTemplate.xml"/>--> | ||
15 | <!-- Do Deprecated --> | ||
16 | <Include file="ChorusProgressFrameTemplate.xml"/> | ||
17 | <Include file="ChorusHealthFrameTemplate.xml"/> | ||
18 | <Include file="ChorusPowerFrameTemplate.xml"/> | ||
19 | <!-- End Deprecated --> | ||
14 | <Include file="ChorusUnitPowerFrameTemplate.xml"/> | ||
15 | <Include file="ChorusUnitPowerStatusBarTemplate.xml"/> | ||
20 | 16 | <Include file="ChorusCastFrameTemplate.xml"/> | <Include file="ChorusCastFrameTemplate.xml"/> |
21 | 17 | <Include file="ChorusUnitNameFrameTemplate.xml"/> | <Include file="ChorusUnitNameFrameTemplate.xml"/> |
22 | 18 | <Include file="ChorusRangeFrameTemplate.xml"/> | <Include file="ChorusRangeFrameTemplate.xml"/> |
File src/ChorusFrame.lua changed (mode: 100644) (index 8ddb83a..91da581) | |||
... | ... | local function applyLayout(self) | |
50 | 50 | self:UnregisterAllEvents(); | self:UnregisterAllEvents(); |
51 | 51 | self:SetScript('OnEvent', nil) | self:SetScript('OnEvent', nil) |
52 | 52 | ||
53 | ChorusPlayerFrameHealthFrame.strategy = 'UnitClass' | ||
54 | ChorusFocusFrameHealthFrame.strategy = 'UnitIsFriend' | ||
55 | ChorusFocusFrameUnitNameFrame.strategy = 'UnitClass' | ||
53 | --[[-- @todo Add separate template for target and focus frames to | ||
54 | account for events unique to the frames, instead of implementing | ||
55 | target and focus frame features for every raid member frame template. | ||
56 | ]] | ||
56 | 57 | ||
57 | ChorusTargetFrameHealthFrame.strategy = 'UnitIsFriend' | ||
58 | ChorusTargetFrameUnitNameFrame.strategy = 'UnitClass' | ||
58 | ChorusFocusFrameHealthStatusBar:SetAttribute('chorus-strategy', 'UnitIsFriend') | ||
59 | ChorusPlayerFrameHealthStatusBar:SetAttribute('chorus-strategy', 'UnitClass') | ||
60 | ChorusTargetFrameHealthStatusBar:SetAttribute('chorus-strategy', 'UnitIsFriend') | ||
59 | 61 | ||
62 | ChorusFocusFrameUnitNameFrame.strategy = 'UnitClass' | ||
63 | ChorusTargetFrameUnitNameFrame.strategy = 'UnitClass' | ||
60 | 64 | end | end |
61 | 65 | ||
62 | 66 | --[[-- | --[[-- |
File src/ChorusHealthFrameTemplate.xml deleted (index 858f085..0000000) | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <Ui xmlns="http://www.blizzard.com/wow/ui/"> | ||
3 | <!-- Requries ChorusProgressFrameTemplate.xml --> | ||
4 | <StatusBar name="ChorusHealthFrameTemplate" inherits="ChorusProgressFrameTemplate" virtual="true"> | ||
5 | <Scripts> | ||
6 | <OnLoad>Chorus.healthFrameMain(self);</OnLoad> | ||
7 | </Scripts> | ||
8 | <Attributes> | ||
9 | <Attribute name="useparent-unit" type="boolean" value="true"/> | ||
10 | </Attributes> | ||
11 | </StatusBar> | ||
12 | <!-- Huge health bar shows percentage, current amount and current deficit in the middle of the frame. --> | ||
13 | <StatusBar name="ChorusHugeHealthFrameTemplate" inherits="ChorusHealthFrameTemplate" virtual="true"> | ||
14 | <Layers> | ||
15 | <Layer level="OVERLAY"> | ||
16 | <FontString name="$parentText1" inherits="ChorusFont12Mono" justifyH="LEFT" justifyV="MIDDLE" setAllPoints="true"/> | ||
17 | <FontString name="$parentText2" inherits="ChorusFont12Mono" justifyH="CENTER" justifyV="MIDDLE" setAllPoints="true"/> | ||
18 | <FontString name="$parentText3" inherits="ChorusFont12Mono" justifyH="RIGHT" justifyV="MIDDLE" setAllPoints="true"> | ||
19 | <Color r="1" g="0" b="0"/> | ||
20 | </FontString> | ||
21 | </Layer> | ||
22 | </Layers> | ||
23 | </StatusBar> | ||
24 | <!-- Large health bar shows percentage and current amount in the middle of the frame. --> | ||
25 | <StatusBar name="ChorusLargeHealthFrameTemplate" inherits="ChorusHealthFrameTemplate" virtual="true"> | ||
26 | <Layers> | ||
27 | <Layer level="OVERLAY"> | ||
28 | <FontString name="$parentText1" inherits="ChorusFont12Mono" justifyH="LEFT" justifyV="MIDDLE" setAllPoints="true"/> | ||
29 | <FontString name="$parentText2" inherits="ChorusFont12Mono" justifyH="RIGHT" justifyV="MIDDLE" setAllPoints="true"/> | ||
30 | </Layer> | ||
31 | </Layers> | ||
32 | </StatusBar> | ||
33 | <!-- Small health bar shows percentage at the bottom of the frame. --> | ||
34 | <StatusBar name="ChorusSmallHealthFrameTemplate" inherits="ChorusHealthFrameTemplate" virtual="true"> | ||
35 | <Layers> | ||
36 | <Layer level="OVERLAY"> | ||
37 | <FontString name="$parentText1" inherits="ChorusFont12Mono" justifyH="LEFT" justifyV="BOTTOM" setAllPoints="true"/> | ||
38 | </Layer> | ||
39 | </Layers> | ||
40 | </StatusBar> | ||
41 | <!-- Tiny health bar shows no amounts. --> | ||
42 | <StatusBar name="ChorusTinyHealthFrameTemplate" inherits="ChorusHealthFrameTemplate" virtual="true"> | ||
43 | </StatusBar> | ||
44 | </Ui> |
File src/ChorusHugeUnitFrameTemplate.xml changed (mode: 100644) (index 5b6fdab..88c8efe) | |||
81 | 81 | </Anchors> | </Anchors> |
82 | 82 | </Frame> | </Frame> |
83 | 83 | <!-- Main --> | <!-- Main --> |
84 | <StatusBar name="$parentHealthFrame" inherits="ChorusHugeHealthFrameTemplate"> | ||
84 | <StatusBar name="$parentHealthStatusBar" inherits="ChorusUnitHealthUnitClassStatusBarTemplate"> | ||
85 | <Size> | ||
86 | <AbsDimension x="200" y="174"/> | ||
87 | </Size> | ||
85 | 88 | <Anchors> | <Anchors> |
86 | 89 | <Anchor point="TOPRIGHT"> | <Anchor point="TOPRIGHT"> |
87 | 90 | <Offset x="0" y="-16"/> | <Offset x="0" y="-16"/> |
91 | 94 | </Anchor> | </Anchor> |
92 | 95 | </Anchors> | </Anchors> |
93 | 96 | </StatusBar> | </StatusBar> |
94 | <StatusBar name="$parentPowerFrame" inherits="ChorusHugePowerFrameTemplate"> | ||
97 | <Frame name="$parentHealthFrame" inherits="ChorusUnitHealthHugeFrameTemplate"> | ||
98 | <Anchors> | ||
99 | <Anchor point="TOPRIGHT"> | ||
100 | <Offset x="0" y="-16"/> | ||
101 | </Anchor> | ||
102 | <Anchor point="BOTTOMLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> | ||
103 | <Offset x="0" y="-40"/> | ||
104 | </Anchor> | ||
105 | </Anchors> | ||
106 | </Frame> | ||
107 | <StatusBar name="$parentPowerStatusBar" inherits="ChorusUnitPowerStatusBarTemplate"> | ||
108 | <Size> | ||
109 | <AbsDimension x="200" y="174"/> | ||
110 | </Size> | ||
95 | 111 | <Anchors> | <Anchors> |
96 | 112 | <Anchor point="TOPRIGHT"> | <Anchor point="TOPRIGHT"> |
97 | 113 | <Offset x="0" y="-40"/> | <Offset x="0" y="-40"/> |
101 | 117 | </Anchor> | </Anchor> |
102 | 118 | </Anchors> | </Anchors> |
103 | 119 | </StatusBar> | </StatusBar> |
120 | <Frame name="$parentPowerFrame" inherits="ChorusUnitPowerLargeFrameTemplate"> | ||
121 | <Anchors> | ||
122 | <Anchor point="TOPRIGHT"> | ||
123 | <Offset x="0" y="-40"/> | ||
124 | </Anchor> | ||
125 | <Anchor point="BOTTOMLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> | ||
126 | <Offset x="0" y="-56"/> | ||
127 | </Anchor> | ||
128 | </Anchors> | ||
129 | </Frame> | ||
104 | 130 | <Frame name="$parentThreatFrame" inherits="ChorusThreatFrameTemplate"> | <Frame name="$parentThreatFrame" inherits="ChorusThreatFrameTemplate"> |
105 | 131 | <Anchors> | <Anchors> |
106 | 132 | <Anchor point="TOPRIGHT"> | <Anchor point="TOPRIGHT"> |
File src/ChorusLargeUnitFrameTemplate.xml changed (mode: 100644) (index ec0627d..c0c799c) | |||
81 | 81 | </Anchors> | </Anchors> |
82 | 82 | </Frame> | </Frame> |
83 | 83 | <!-- Main --> | <!-- Main --> |
84 | <StatusBar name="$parentHealthFrame" inherits="ChorusHugeHealthFrameTemplate"> | ||
84 | <StatusBar name="$parentHealthStatusBar" inherits="ChorusUnitHealthUnitClassStatusBarTemplate"> | ||
85 | <Size> | ||
86 | <AbsDimension x="160" y="130"/> | ||
87 | </Size> | ||
85 | 88 | <Anchors> | <Anchors> |
86 | 89 | <Anchor point="TOPRIGHT"> | <Anchor point="TOPRIGHT"> |
87 | 90 | <Offset x="0" y="-16"/> | <Offset x="0" y="-16"/> |
91 | 94 | </Anchor> | </Anchor> |
92 | 95 | </Anchors> | </Anchors> |
93 | 96 | </StatusBar> | </StatusBar> |
94 | <StatusBar name="$parentPowerFrame" inherits="ChorusHugePowerFrameTemplate"> | ||
97 | <Frame name="$parentHealthFrame" inherits="ChorusUnitHealthLargeFrameTemplate"> | ||
98 | <Anchors> | ||
99 | <Anchor point="TOPRIGHT"> | ||
100 | <Offset x="0" y="-16"/> | ||
101 | </Anchor> | ||
102 | <Anchor point="BOTTOMLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> | ||
103 | <Offset x="0" y="-40"/> | ||
104 | </Anchor> | ||
105 | </Anchors> | ||
106 | </Frame> | ||
107 | <StatusBar name="$parentPowerStatusBar" inherits="ChorusUnitPowerStatusBarTemplate"> | ||
108 | <Size> | ||
109 | <AbsDimension x="160" y="130"/> | ||
110 | </Size> | ||
95 | 111 | <Anchors> | <Anchors> |
96 | 112 | <Anchor point="TOPRIGHT"> | <Anchor point="TOPRIGHT"> |
97 | 113 | <Offset x="0" y="-40"/> | <Offset x="0" y="-40"/> |
101 | 117 | </Anchor> | </Anchor> |
102 | 118 | </Anchors> | </Anchors> |
103 | 119 | </StatusBar> | </StatusBar> |
120 | <Frame name="$parentPowerFrame" inherits="ChorusUnitPowerLargeFrameTemplate"> | ||
121 | <Anchors> | ||
122 | <Anchor point="TOPRIGHT"> | ||
123 | <Offset x="0" y="-40"/> | ||
124 | </Anchor> | ||
125 | <Anchor point="BOTTOMLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> | ||
126 | <Offset x="0" y="-56"/> | ||
127 | </Anchor> | ||
128 | </Anchors> | ||
129 | </Frame> | ||
104 | 130 | <Frame name="$parentThreatFrame" inherits="ChorusThreatFrameTemplate"> | <Frame name="$parentThreatFrame" inherits="ChorusThreatFrameTemplate"> |
105 | 131 | <Anchors> | <Anchors> |
106 | 132 | <Anchor point="TOPRIGHT"> | <Anchor point="TOPRIGHT"> |
File src/ChorusPowerFrameTemplate.xml deleted (index c34dbb7..0000000) | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <Ui xmlns="http://www.blizzard.com/wow/ui/"> | ||
3 | <!-- Requries ChorusProgressFrameTemplate.xml --> | ||
4 | <StatusBar name="ChorusPowerFrameTemplate" inherits="ChorusProgressFrameTemplate" virtual="true"> | ||
5 | <Scripts> | ||
6 | <OnLoad>Chorus.powerFrameMain(self);</OnLoad> | ||
7 | </Scripts> | ||
8 | <Attributes> | ||
9 | <Attribute name="useparent-unit" type="boolean" value="true"/> | ||
10 | </Attributes> | ||
11 | </StatusBar> | ||
12 | <StatusBar name="ChorusHugePowerFrameTemplate" inherits="ChorusPowerFrameTemplate" virtual="true"> | ||
13 | <Layers> | ||
14 | <Layer level="OVERLAY"> | ||
15 | <FontString name="$parentText1" inherits="ChorusFont12Mono" justifyH="LEFT" justifyV="MIDDLE" setAllPoints="true"/> | ||
16 | <FontString name="$parentText2" inherits="ChorusFont12Mono" justifyH="RIGHT" justifyV="MIDDLE" setAllPoints="true"/> | ||
17 | </Layer> | ||
18 | </Layers> | ||
19 | </StatusBar> | ||
20 | <StatusBar name="ChorusLargePowerFrameTemplate" inherits="ChorusHugePowerFrameTemplate" virtual="true"/> | ||
21 | <StatusBar name="ChorusSmallPowerFrameTemplate" inherits="ChorusPowerFrameTemplate" virtual="true"> | ||
22 | <Layers> | ||
23 | <Layer level="OVERLAY"> | ||
24 | <FontString name="$parentText1" inherits="ChorusFont12Mono" justifyH="LEFT" justifyV="BOTTOM" setAllPoints="true"/> | ||
25 | </Layer> | ||
26 | </Layers> | ||
27 | </StatusBar> | ||
28 | <StatusBar name="ChorusTinyPowerFrameTemplate" inherits="ChorusPowerFrameTemplate" virtual="true"> | ||
29 | </StatusBar> | ||
30 | </Ui> |
File src/ChorusProgressFrameTemplate.lua deleted (index b1fa384..0000000) | |||
1 | --[[-- | ||
2 | @submodule chorus | ||
3 | ]] | ||
4 | |||
5 | local Chorus = Chorus | ||
6 | |||
7 | local UnitClass = Chorus.test.UnitClass or UnitClass | ||
8 | local UnitExists = Chorus.test.UnitExists or UnitExists | ||
9 | local UnitHealth = Chorus.test.UnitHealth or UnitHealth | ||
10 | local UnitHealthMax = Chorus.test.UnitHealthMax or UnitHealthMax | ||
11 | local UnitIsConnected = Chorus.test.UnitIsConnected or UnitIsConnected | ||
12 | local UnitIsCorpse = Chorus.test.UnitIsCorpse or UnitIsCorpse | ||
13 | local UnitIsDead = Chorus.test.UnitIsDead or UnitIsDead | ||
14 | local UnitIsGhost = Chorus.test.UnitIsGhost or UnitIsGhost | ||
15 | local UnitIsPlayer = Chorus.test.UnitIsPlayer or UnitIsPlayer | ||
16 | local UnitPower = Chorus.test.UnitPower or UnitPower | ||
17 | local UnitPowerMax = Chorus.test.UnitPowerMax or UnitPowerMax | ||
18 | local UnitPowerType = Chorus.test.UnitPowerType or UnitPowerType | ||
19 | |||
20 | --[[ See `FrameXML/GlobalStrings.lua`. ]]-- | ||
21 | local CORPSE = CORPSE or 'CORPSE' | ||
22 | local DEAD = DEAD or 'DEAD' | ||
23 | local DEATH_RELEASE = DEATH_RELEASE or 'DEATH_RELEASE' | ||
24 | local PLAYER_OFFLINE = PLAYER_OFFLINE or 'PLAYER_OFFLINE' | ||
25 | |||
26 | local PowerBarColor = PowerBarColor | ||
27 | local RAID_CLASS_COLORS = RAID_CLASS_COLORS | ||
28 | local SecureButton_GetUnit = Chorus.test.SecureButton_GetUnit or SecureButton_GetUnit | ||
29 | |||
30 | local function validateProgressFrame(self) | ||
31 | assert(self ~= nil) | ||
32 | |||
33 | local artwork = self.artwork | ||
34 | assert(artwork ~= nil) | ||
35 | |||
36 | local ratio = self:GetValue() | ||
37 | assert(ratio ~= nil) | ||
38 | assert('number' == type(ratio)) | ||
39 | assert(ratio >= 0.0) | ||
40 | assert(ratio <= 1.0) | ||
41 | |||
42 | local strategy = self.strategy | ||
43 | if strategy then | ||
44 | assert('string' == type(strategy)) | ||
45 | strategy = strtrim(strategy) | ||
46 | assert(string.len(strategy) >= 1) | ||
47 | assert(string.len(strategy) <= 8192) | ||
48 | end | ||
49 | end | ||
50 | |||
51 | local function getRatio(a, b) | ||
52 | if not a or not b then | ||
53 | return 0 | ||
54 | end | ||
55 | |||
56 | assert(a ~= nil) | ||
57 | assert('number' == type(a)) | ||
58 | assert(a >= 0) | ||
59 | |||
60 | if a <= 0 or b <= 0 then | ||
61 | return 0 | ||
62 | end | ||
63 | |||
64 | assert(b ~= nil) | ||
65 | assert('number' == type(b)) | ||
66 | assert(b > 0) | ||
67 | |||
68 | assert(a <= b) | ||
69 | |||
70 | local x = math.min(math.abs(a), math.abs(b)) | ||
71 | local y = math.max(math.abs(a), math.abs(b)) | ||
72 | y = math.max(y, 1) | ||
73 | assert(y > 0) | ||
74 | |||
75 | local ratio = x / y | ||
76 | ratio = math.min(math.max(0, math.abs(ratio)), 1) | ||
77 | |||
78 | return ratio | ||
79 | end | ||
80 | |||
81 | local function applyRatio(self, a, b) | ||
82 | assert(self ~= nil) | ||
83 | |||
84 | local ratio = 0 | ||
85 | |||
86 | --[[ Strict sanitization to work around WoW API quirks. ]]-- | ||
87 | if a and b then | ||
88 | assert('number' == type(a)) | ||
89 | assert('number' == type(b)) | ||
90 | local x = math.min(a, b) | ||
91 | local y = math.max(a, b) | ||
92 | if x <= y then | ||
93 | ratio = getRatio(x, y) | ||
94 | end | ||
95 | end | ||
96 | |||
97 | self:SetValue(ratio) | ||
98 | end | ||
99 | |||
100 | local function formatQuantity(quantity) | ||
101 | assert(quantity ~= nil) | ||
102 | assert('number' == type(quantity)) | ||
103 | |||
104 | local t | ||
105 | if math.abs(quantity) < 1000 then | ||
106 | t = string.format('%d',quantity) | ||
107 | elseif math.abs(quantity) < 1000000 then | ||
108 | t = string.format('%.2f K', quantity / 1000) | ||
109 | else | ||
110 | t = string.format('%.2f M', quantity / 1000000) | ||
111 | end | ||
112 | |||
113 | return t | ||
114 | end | ||
115 | |||
116 | local function applyOverlay(self, a, b) | ||
117 | assert(self ~= nil) | ||
118 | |||
119 | assert(a ~= nil) | ||
120 | assert('number' == type(a)) | ||
121 | assert(a >= 0) | ||
122 | |||
123 | assert(b ~= nil) | ||
124 | assert('number' == type(b)) | ||
125 | --[[ Work around quirks of the native API. ]]-- | ||
126 | b = math.max(b, 1) | ||
127 | assert(b > 0) | ||
128 | |||
129 | if a > b then | ||
130 | return | ||
131 | end | ||
132 | assert(a <= b) | ||
133 | |||
134 | local ratio = getRatio(a, b) | ||
135 | |||
136 | local label1 = self.label1 or _G[self:GetName() .. 'Text1'] | ||
137 | if label1 then | ||
138 | local e = string.format('%.0f%%', ratio * 100) | ||
139 | label1:SetText(e) | ||
140 | |||
141 | --[[ ShadowedUnitFrames recommend this approach for adjusting font size. ]]-- | ||
142 | if e ~= nil and string.len(e) >= 1 then | ||
143 | local fontSize = 12 | ||
144 | self:SetScale(label1:GetStringHeight() / fontSize) | ||
145 | end | ||
146 | else | ||
147 | return | ||
148 | end | ||
149 | |||
150 | local label2 = self.label2 or _G[self:GetName() .. 'Text2'] | ||
151 | if label2 then | ||
152 | local t = formatQuantity(a) | ||
153 | label2:SetText(t) | ||
154 | |||
155 | --[[ ShadowedUnitFrames recommend this approach for adjusting font size. ]]-- | ||
156 | if t ~= nil and string.len(t) >= 1 then | ||
157 | local fontSize = 12 | ||
158 | self:SetScale(label2:GetStringHeight() / fontSize) | ||
159 | end | ||
160 | else | ||
161 | return | ||
162 | end | ||
163 | end | ||
164 | |||
165 | local function applyRatioHealth(self, unitDesignation) | ||
166 | assert(self ~= nil) | ||
167 | |||
168 | assert(unitDesignation ~= nil) | ||
169 | |||
170 | local a | ||
171 | local b | ||
172 | if not UnitExists(unitDesignation) or | ||
173 | not UnitIsConnected(unitDesignation) or | ||
174 | UnitIsDead(unitDesignation) or | ||
175 | UnitIsCorpse(unitDesignation) or | ||
176 | UnitIsGhost(unitDesignation) then | ||
177 | a = 0 | ||
178 | b = 1 | ||
179 | else | ||
180 | a = UnitHealth(unitDesignation) or 0 | ||
181 | b = UnitHealthMax(unitDesignation) or 1 | ||
182 | end | ||
183 | |||
184 | applyRatio(self, a, b) | ||
185 | end | ||
186 | |||
187 | local function applyOverlayHealthDeficit(self, a, b) | ||
188 | assert(self ~= nil) | ||
189 | |||
190 | local label3 = self.label3 or _G[self:GetName() .. 'Text3'] | ||
191 | if not label3 then | ||
192 | return | ||
193 | end | ||
194 | |||
195 | if a and b and a >= 1 and b >= 1 and a < b then | ||
196 | local c = a - b | ||
197 | local t = formatQuantity(c) | ||
198 | label3:SetText(t) | ||
199 | else | ||
200 | label3:SetText(nil) | ||
201 | end | ||
202 | end | ||
203 | |||
204 | --[[-- | ||
205 | Update this health frame with the state of the given unit. | ||
206 | |||
207 | @see FrameXML/GlobalStrings.lua:CORPSE | ||
208 | |||
209 | @function applyOverlayHealth | ||
210 | @tparam frame self this health frame | ||
211 | @tparam string unitDesignation given unit | ||
212 | ]] | ||
213 | local function applyOverlayHealth(self, unitDesignation) | ||
214 | assert(self ~= nil) | ||
215 | |||
216 | assert(unitDesignation ~= nil) | ||
217 | |||
218 | local u = unitDesignation | ||
219 | local a = UnitHealth(u) | ||
220 | local b = UnitHealthMax(u) | ||
221 | |||
222 | if a and b and a <= b and b >= 1 and | ||
223 | UnitExists(u) and | ||
224 | UnitIsConnected(u) and | ||
225 | not UnitIsDead(u) and | ||
226 | not UnitIsCorpse(u) and | ||
227 | not UnitIsGhost(u) then | ||
228 | applyOverlay(self, a, b) | ||
229 | applyOverlayHealthDeficit(self, a, b) | ||
230 | else | ||
231 | --[[-- @todo Separate health status bar and unit statues. | ||
232 | ]] | ||
233 | local t = {self.label1, self.label2, self.label3} | ||
234 | local i = 0 | ||
235 | while (i < #t) do | ||
236 | i = i + 1 | ||
237 | local label = t[i] | ||
238 | if label then | ||
239 | label:SetText(nil) | ||
240 | end | ||
241 | end | ||
242 | |||
243 | local label1 = self.label1 | ||
244 | if not label1 then | ||
245 | return | ||
246 | end | ||
247 | |||
248 | local s = nil | ||
249 | if UnitIsCorpse(unitDesignation) then | ||
250 | s = '(' .. (CORPSE or 'CORPSE') .. ')' | ||
251 | elseif UnitIsGhost(unitDesignation) then | ||
252 | s = '(' .. (DEATH_RELEASE or 'GHOST') .. ')' | ||
253 | elseif UnitIsDead(unitDesignation) then | ||
254 | s = '(' .. (DEAD or 'DEAD') .. ')' | ||
255 | elseif not UnitIsConnected(unitDesignation) then | ||
256 | ---- @fixme The 'Player offline' label is never rendered. | ||
257 | |||
258 | ---- @todo Add separate offline indicator widget. | ||
259 | s = '(' .. (PLAYER_OFFLINE or 'PLAYER_OFFLINE') .. ')' | ||
260 | end | ||
261 | label1:SetText(s) | ||
262 | end | ||
263 | end | ||
264 | |||
265 | local function applyRatioPower(self, unitDesignation, powerTypeEnum) | ||
266 | assert(self ~= nil) | ||
267 | assert(unitDesignation ~= nil) | ||
268 | assert(powerTypeEnum ~= nil) | ||
269 | |||
270 | local a = UnitPower(unitDesignation, powerTypeEnum) or 0 | ||
271 | local b = UnitPowerMax(unitDesignation, powerTypeEnum) or 1 | ||
272 | applyRatio(self, a, b) | ||
273 | end | ||
274 | |||
275 | local function applyOverlayPower(self, unitDesignation, powerTypeEnum) | ||
276 | assert(self ~= nil) | ||
277 | assert(unitDesignation ~= nil) | ||
278 | assert(powerTypeEnum ~= nil) | ||
279 | |||
280 | local a = UnitPower(unitDesignation, powerTypeEnum) or 0 | ||
281 | local b = UnitPowerMax(unitDesignation, powerTypeEnum) or 1 | ||
282 | applyOverlay(self, a, b) | ||
283 | end | ||
284 | |||
285 | local function applyHealthFrameColorUnitClass(self, unitDesignation) | ||
286 | assert(self ~= nil) | ||
287 | assert(unitDesignation ~= nil) | ||
288 | |||
289 | local _, classDesignation = UnitClass(unitDesignation) | ||
290 | if not classDesignation then | ||
291 | return | ||
292 | end | ||
293 | |||
294 | local map = RAID_CLASS_COLORS | ||
295 | assert(map ~= nil) | ||
296 | assert('table' == type(map)) | ||
297 | local colorTuple = map[classDesignation] | ||
298 | |||
299 | local r = 1 | ||
300 | local g = 1 | ||
301 | local b = 1 | ||
302 | if colorTuple then | ||
303 | assert('table' == type(colorTuple)) | ||
304 | r = math.min(math.max(0, math.abs(colorTuple.r)), 1) | ||
305 | g = math.min(math.max(0, math.abs(colorTuple.g)), 1) | ||
306 | b = math.min(math.max(0, math.abs(colorTuple.b)), 1) | ||
307 | end | ||
308 | |||
309 | local artwork = self.artwork | ||
310 | assert(artwork ~= nil) | ||
311 | |||
312 | local image = artwork:GetTexture() | ||
313 | if image then | ||
314 | artwork:SetVertexColor(r, g, b) | ||
315 | else | ||
316 | artwork:SetTexture(r, g, b) | ||
317 | end | ||
318 | end | ||
319 | |||
320 | local function applyHealthFrameColorUnitIsFriend(self, unitDesignation) | ||
321 | assert(self ~= nil) | ||
322 | assert(unitDesignation ~= nil) | ||
323 | |||
324 | local r = 255 / 255 | ||
325 | local g = 215 / 255 | ||
326 | local b = 0 / 255 | ||
327 | |||
328 | if UnitIsFriend('player', unitDesignation) then | ||
329 | r = 124 / 255 | ||
330 | g = 252 / 255 | ||
331 | b = 0 / 255 | ||
332 | elseif UnitIsEnemy('player', unitDesignation) then | ||
333 | r = 255 / 255 | ||
334 | g = 69 / 255 | ||
335 | b = 0 / 255 | ||
336 | end | ||
337 | |||
338 | local artwork = self.artwork | ||
339 | assert(artwork ~= nil) | ||
340 | |||
341 | local image = artwork:GetTexture() | ||
342 | if image then | ||
343 | artwork:SetVertexColor(r, g, b) | ||
344 | else | ||
345 | artwork:SetTexture(r, g, b) | ||
346 | end | ||
347 | end | ||
348 | |||
349 | local function healthFrameEventIsRelevant(self, eventCategory, ...) | ||
350 | assert(self ~= nil) | ||
351 | |||
352 | assert(eventCategory ~= nil) | ||
353 | |||
354 | local targetUnit = select(1, ...) | ||
355 | if targetUnit then | ||
356 | local unitDesignation = SecureButton_GetUnit(self) or 'none' | ||
357 | return UnitIsUnit(unitDesignation, targetUnit) | ||
358 | end | ||
359 | return true | ||
360 | end | ||
361 | |||
362 | local function healthFrameEventProcessor(self, eventCategory, ...) | ||
363 | validateProgressFrame(self) | ||
364 | |||
365 | if not healthFrameEventIsRelevant(self, eventCategory, ...) then | ||
366 | return | ||
367 | end | ||
368 | |||
369 | local unitDesignation = SecureButton_GetUnit(self) or 'none' | ||
370 | |||
371 | assert(unitDesignation ~= nil) | ||
372 | assert('string' == type(unitDesignation)) | ||
373 | unitDesignation = string.lower(strtrim(unitDesignation)) | ||
374 | assert(string.len(unitDesignation) >= 1) | ||
375 | assert(string.len(unitDesignation) <= 256) | ||
376 | |||
377 | if UnitExists(unitDesignation) and UnitIsConnected(unitDesignation) then | ||
378 | self:Show() | ||
379 | else | ||
380 | self:Hide() | ||
381 | return | ||
382 | end | ||
383 | |||
384 | applyRatioHealth(self, unitDesignation) | ||
385 | applyOverlayHealth(self, unitDesignation) | ||
386 | |||
387 | local strategy = self.strategy | ||
388 | assert(strategy ~= nil) | ||
389 | assert('string' == type(strategy)) | ||
390 | strategy = strtrim(strategy) | ||
391 | assert(string.len(strategy) >= 1) | ||
392 | assert(string.len(strategy) <= 256) | ||
393 | |||
394 | assert(strategy == 'UnitClass' or strategy == 'UnitIsFriend') | ||
395 | |||
396 | if 'UnitClass' == strategy then | ||
397 | --[[ `function UnitClass` only works for player units. ]]-- | ||
398 | if UnitIsPlayer(unitDesignation) then | ||
399 | applyHealthFrameColorUnitClass(self, unitDesignation) | ||
400 | else | ||
401 | applyHealthFrameColorUnitIsFriend(self, unitDesignation) | ||
402 | end | ||
403 | elseif 'UnitIsFriend' == strategy then | ||
404 | applyHealthFrameColorUnitIsFriend(self, unitDesignation) | ||
405 | else | ||
406 | error('invalid enum: strategy must be either UnitClass or UnitIsFriend') | ||
407 | end | ||
408 | end | ||
409 | |||
410 | local function applyPowerFrameColor(self, powerTypeEnum) | ||
411 | assert(self ~= nil) | ||
412 | |||
413 | local r = 1 | ||
414 | local g = 0 | ||
415 | local b = 1 | ||
416 | if powerTypeEnum then | ||
417 | --[[ See FrameXML/UnitFrame.lua:PowerBarColor ]]-- | ||
418 | local map = PowerBarColor | ||
419 | assert(map ~= nil) | ||
420 | assert('table' == type(map)) | ||
421 | |||
422 | local colorTuple = map[powerTypeEnum] | ||
423 | if colorTuple then | ||
424 | assert('table' == type(colorTuple)) | ||
425 | r = math.min(math.max(0, math.abs(colorTuple.r)), 1) | ||
426 | g = math.min(math.max(0, math.abs(colorTuple.g)), 1) | ||
427 | b = math.min(math.max(0, math.abs(colorTuple.b)), 1) | ||
428 | end | ||
429 | end | ||
430 | |||
431 | local artwork = self.artwork | ||
432 | assert(artwork ~= nil) | ||
433 | |||
434 | local image = artwork:GetTexture() | ||
435 | if image then | ||
436 | artwork:SetVertexColor(r, g, b) | ||
437 | else | ||
438 | artwork:SetTexture(r, g, b) | ||
439 | end | ||
440 | end | ||
441 | |||
442 | local function powerFrameEventProcessor(self, eventCategory, ...) | ||
443 | validateProgressFrame(self) | ||
444 | |||
445 | if not healthFrameEventIsRelevant(self, eventCategory, ...) then | ||
446 | return | ||
447 | end | ||
448 | |||
449 | local unitDesignation = SecureButton_GetUnit(self) or 'none' | ||
450 | |||
451 | assert(unitDesignation ~= nil) | ||
452 | assert('string' == type(unitDesignation)) | ||
453 | unitDesignation = string.lower(strtrim(unitDesignation)) | ||
454 | assert(string.len(unitDesignation) >= 1) | ||
455 | assert(string.len(unitDesignation) <= 256) | ||
456 | |||
457 | if UnitExists(unitDesignation) and UnitIsConnected(unitDesignation) and UnitPowerMax(unitDesignation) >= 1 then | ||
458 | self:Show() | ||
459 | else | ||
460 | self:Hide() | ||
461 | return | ||
462 | end | ||
463 | |||
464 | local powerTypeEnum | ||
465 | local strategy = self.strategy | ||
466 | assert(strategy ~= nil) | ||
467 | assert('string' == type(strategy)) | ||
468 | strategy = strtrim(strategy) | ||
469 | assert(string.len(strategy) >= 1) | ||
470 | assert(string.len(strategy) <= 256) | ||
471 | if 'UnitPowerType' == strategy then | ||
472 | local enum, category = UnitPowerType(unitDesignation) | ||
473 | if category then | ||
474 | powerTypeEnum = enum | ||
475 | else | ||
476 | self:Hide() | ||
477 | return | ||
478 | end | ||
479 | else | ||
480 | --[[ See FrameXML/Constants.lua:SPELL_POWER_MANA ]]-- | ||
481 | powerTypeEnum = _G[strategy] | ||
482 | end | ||
483 | assert(powerTypeEnum ~= nil) | ||
484 | assert('number' == type(powerTypeEnum)) | ||
485 | assert(powerTypeEnum >= 0) | ||
486 | powerTypeEnum = math.min(math.max(0, math.floor(math.abs(powerTypeEnum))), 8192) | ||
487 | |||
488 | if UnitPowerMax(unitDesignation, powerTypeEnum) >= 1 then | ||
489 | self:Show() | ||
490 | applyRatioPower(self, unitDesignation, powerTypeEnum) | ||
491 | applyOverlayPower(self, unitDesignation, powerTypeEnum) | ||
492 | applyPowerFrameColor(self, powerTypeEnum) | ||
493 | else | ||
494 | self:Hide() | ||
495 | end | ||
496 | end | ||
497 | |||
498 | --[[-- | ||
499 | `ChorusProgressFrameTemplate` is a generalization for health bars and power | ||
500 | (mana) bars. | ||
501 | |||
502 | The features are shared between both health and power bars, but there exist | ||
503 | separate corresponding templates: `ChorusHealthFrameTemplate` and | ||
504 | `ChorusPowerFrameTemplate`. | ||
505 | |||
506 | Frames that inherit from this template may define field `strategy`. This field | ||
507 | may be either `UnitIsFriend` or `UnitPowerType`. The bar will be colored by | ||
508 | either unit reaction to the player, or the power type (blue for mana, red for | ||
509 | rage, etc.). | ||
510 | |||
511 | @function progressFrameMain | ||
512 | ]] | ||
513 | function Chorus.progressFrameMain(self) | ||
514 | assert(self ~= nil) | ||
515 | |||
516 | local frameDesignation = self:GetName() | ||
517 | assert(frameDesignation ~= nil) | ||
518 | assert('string' == type(frameDesignation)) | ||
519 | frameDesignation = strtrim(frameDesignation) | ||
520 | assert(string.len(frameDesignation) >= 1) | ||
521 | assert(string.len(frameDesignation) <= 256) | ||
522 | |||
523 | local artwork = _G[frameDesignation .. 'Artwork'] | ||
524 | assert(artwork ~= nil, self:GetName() .. ': invalid state') | ||
525 | self.artwork = artwork | ||
526 | |||
527 | local label1 = _G[frameDesignation .. 'Text1'] or nil | ||
528 | self.label1 = label1 | ||
529 | |||
530 | local label2 = _G[frameDesignation .. 'Text2'] or nil | ||
531 | self.label2 = label2 | ||
532 | |||
533 | local label3 = _G[frameDesignation .. 'Text3'] or nil | ||
534 | self.label3 = label3 | ||
535 | |||
536 | self:RegisterEvent('PARTY_CONVERTED_TO_RAID') | ||
537 | self:RegisterEvent('PARTY_MEMBERS_CHANGED') | ||
538 | self:RegisterEvent('PARTY_MEMBER_DISABLE') | ||
539 | self:RegisterEvent('PARTY_MEMBER_ENABLE') | ||
540 | self:RegisterEvent('PLAYER_ALIVE') | ||
541 | self:RegisterEvent('PLAYER_FOCUS_CHANGED') | ||
542 | self:RegisterEvent('PLAYER_LOGIN') | ||
543 | self:RegisterEvent('PLAYER_TARGET_CHANGED') | ||
544 | self:RegisterEvent('RAID_ROSTER_UPDATE') | ||
545 | |||
546 | self:SetMinMaxValues(0, 1) | ||
547 | self:SetValue(1) | ||
548 | end | ||
549 | |||
550 | function Chorus.healthFrameMain(self, ...) | ||
551 | Chorus.progressFrameMain(self, ...) | ||
552 | self.strategy = 'UnitIsFriend' | ||
553 | self:SetScript('OnEvent', healthFrameEventProcessor) | ||
554 | |||
555 | self:RegisterEvent('UNIT_HEALTH') | ||
556 | end | ||
557 | |||
558 | function Chorus.powerFrameMain(self, ...) | ||
559 | Chorus.progressFrameMain(self, ...) | ||
560 | self.strategy = 'UnitPowerType' | ||
561 | self:SetScript('OnEvent', powerFrameEventProcessor) | ||
562 | |||
563 | self:RegisterEvent('UNIT_ENERGY') | ||
564 | self:RegisterEvent('UNIT_MANA') | ||
565 | self:RegisterEvent('UNIT_MAXPOWER') | ||
566 | self:RegisterEvent('UNIT_POWER') | ||
567 | self:RegisterEvent('UNIT_RAGE') | ||
568 | self:RegisterEvent('UNIT_RUNIC_POWER') | ||
569 | end |
File src/ChorusSmallUnitFrameTemplate.xml changed (mode: 100644) (index c48bcf1..401cd08) | |||
38 | 38 | </Anchors> | </Anchors> |
39 | 39 | </Frame> | </Frame> |
40 | 40 | <!-- Main --> | <!-- Main --> |
41 | <StatusBar name="$parentHealthFrame" inherits="ChorusSmallHealthFrameTemplate"> | ||
41 | <StatusBar name="$parentHealthStatusBar" inherits="ChorusUnitHealthUnitClassStatusBarTemplate"> | ||
42 | <Size> | ||
43 | <AbsDimension x="96" y="48"/> | ||
44 | </Size> | ||
42 | 45 | <Anchors> | <Anchors> |
43 | 46 | <Anchor point="TOPRIGHT"> | <Anchor point="TOPRIGHT"> |
44 | 47 | <Offset x="0" y="0"/> | <Offset x="0" y="0"/> |
48 | 51 | </Anchor> | </Anchor> |
49 | 52 | </Anchors> | </Anchors> |
50 | 53 | </StatusBar> | </StatusBar> |
51 | <StatusBar name="$parentPowerFrame" inherits="ChorusTinyPowerFrameTemplate"> | ||
54 | <Frame name="$parentHealthFrame" inherits="ChorusUnitHealthSmallFrameTemplate"> | ||
55 | <Anchors> | ||
56 | <Anchor point="TOPRIGHT"> | ||
57 | <Offset x="0" y="0"/> | ||
58 | </Anchor> | ||
59 | <Anchor point="BOTTOMLEFT"> | ||
60 | <Offset x="0" y="6"/> | ||
61 | </Anchor> | ||
62 | </Anchors> | ||
63 | </Frame> | ||
64 | <StatusBar name="$parentPowerStatusBar" inherits="ChorusUnitPowerStatusBarTemplate"> | ||
65 | <Size> | ||
66 | <AbsDimension x="96" y="48"/> | ||
67 | </Size> | ||
52 | 68 | <Anchors> | <Anchors> |
53 | 69 | <Anchor point="TOPRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT"> | <Anchor point="TOPRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT"> |
54 | 70 | <Offset x="0" y="6"/> | <Offset x="0" y="6"/> |
60 | 76 | </StatusBar> | </StatusBar> |
61 | 77 | <Frame name="$parentBuffFrame" inherits="ChorusSmallAuraFrameTemplate"> | <Frame name="$parentBuffFrame" inherits="ChorusSmallAuraFrameTemplate"> |
62 | 78 | <Anchors> | <Anchors> |
63 | <Anchor point="TOPLEFT" relativeTo="$parentUnitNameFrame" relativePoint="BOTTOMLEFT"> | ||
64 | <Offset x="0" y="0"/> | ||
79 | <Anchor point="BOTTOMLEFT" relativeTo="$parent" relativePoint="BOTTOMLEFT"> | ||
80 | <Offset x="0" y="6"/> | ||
65 | 81 | </Anchor> | </Anchor> |
66 | 82 | </Anchors> | </Anchors> |
67 | 83 | <Attributes> | <Attributes> |
File src/ChorusTinyUnitFrameTemplate.xml changed (mode: 100644) (index 3b64225..19f3ec8) | |||
22 | 22 | </Anchors> | </Anchors> |
23 | 23 | </Frame> | </Frame> |
24 | 24 | <!-- Main --> | <!-- Main --> |
25 | <StatusBar name="$parentHealthFrame" inherits="ChorusTinyHealthFrameTemplate" setAllPoints="true"/> | ||
25 | <StatusBar name="$parentHealthStatusBar" inherits="ChorusUnitHealthUnitClassStatusBarTemplate" setAllPoints="true"/> | ||
26 | 26 | </Frames> | </Frames> |
27 | 27 | </Frame> | </Frame> |
28 | 28 | </Ui> | </Ui> |
File src/ChorusUnitFrameTemplate.lua changed (mode: 100644) (index d64b953..6aa019c) | |||
... | ... | local function applyTOT(self) | |
25 | 25 | return | return |
26 | 26 | end | end |
27 | 27 | ||
28 | local unitNameFrame = self.unitNameFrame | ||
29 | if unitNameFrame then | ||
30 | local callback0 = unitNameFrame:GetScript('OnEvent') | ||
31 | callback0(unitNameFrame, 'UNIT_NAME_UPDATE', u) | ||
32 | end | ||
33 | |||
34 | local healthFrame = self.healthFrame | ||
35 | if healthFrame then | ||
36 | local callback1 = healthFrame:GetScript('OnEvent') | ||
37 | callback1(healthFrame, 'UNIT_HEALTH', u) | ||
38 | end | ||
39 | |||
40 | local powerFrame = self.powerFrame | ||
41 | if powerFrame then | ||
42 | local callback2 = powerFrame:GetScript('OnEvent') | ||
43 | callback2(powerFrame, 'UNIT_POWER', u) | ||
44 | end | ||
45 | |||
46 | --[[ Notify backdrop to toggle visibility when appropriate. ]]-- | ||
47 | local backdropFrame = self.backdropFrame | ||
48 | if backdropFrame then | ||
49 | local callback3 = backdropFrame:GetScript('OnEvent') | ||
50 | --[[ Skip checks and error handing for performance. ]]-- | ||
51 | callback3(backdropFrame) | ||
52 | end | ||
53 | |||
54 | --[[-- @fixme Optimize target of target frames. | ||
55 | ]] | ||
56 | |||
57 | local buffFrame = self.buffFrame | ||
58 | if buffFrame then | ||
59 | local callback4 = buffFrame:GetScript('OnEvent') | ||
60 | callback4(buffFrame, 'UNIT_AURA', u) | ||
61 | end | ||
62 | |||
63 | local debuffFrame = self.debuffFrame | ||
64 | if debuffFrame then | ||
65 | local callback5 = debuffFrame:GetScript('OnEvent') | ||
66 | callback5(debuffFrame, 'UNIT_AURA', u) | ||
28 | local t = {self:GetChildren()} | ||
29 | local i = 0 | ||
30 | while(i < #t) do | ||
31 | i = i + 1 | ||
32 | local f = t[i] | ||
33 | if f then | ||
34 | local callback = f:GetScript('OnEvent') | ||
35 | if callback then | ||
36 | callback(f, 'PLAYER_LOGIN') | ||
37 | end | ||
38 | end | ||
67 | 39 | end | end |
68 | 40 | end | end |
69 | 41 | ||
... | ... | local function applyUnitInRange(self) | |
84 | 56 | return | return |
85 | 57 | end | end |
86 | 58 | ||
87 | --[[ Only apply transparency to select subset of children or referenced | ||
88 | frames. Specifically exclude ChorusAuraTooltipFrame instances. ]]-- | ||
89 | |||
90 | local healthFrame = self.healthFrame | ||
91 | local powerFrame = self.powerFrame | ||
92 | local buffFrame = self.buffFrame | ||
93 | local debuffFrame = self.debuffFrame | ||
94 | |||
95 | if healthFrame then | ||
96 | healthFrame:SetAlpha(a) | ||
97 | end | ||
98 | |||
99 | if powerFrame then | ||
100 | powerFrame:SetAlpha(a) | ||
101 | end | ||
102 | |||
103 | if buffFrame then | ||
104 | buffFrame:SetAlpha(a) | ||
105 | end | ||
106 | |||
107 | if debuffFrame then | ||
108 | debuffFrame:SetAlpha(a) | ||
109 | end | ||
59 | self:SetAlpha(a) | ||
110 | 60 | end | end |
111 | 61 | ||
112 | 62 | function Chorus.unitFrameUnitInRangeUpdateProcessor(self) | function Chorus.unitFrameUnitInRangeUpdateProcessor(self) |
... | ... | end | |
272 | 222 | ||
273 | 223 | local function unitMemberFrameMain(self, ...) | local function unitMemberFrameMain(self, ...) |
274 | 224 | unitFrameMain(self, ...) | unitFrameMain(self, ...) |
225 | end | ||
226 | |||
227 | local function unitTOTFrameMain(self, ...) | ||
228 | unitFrameMain(self, ...) | ||
275 | 229 | ||
276 | local healthFrame = self.healthFrame | ||
277 | if healthFrame then | ||
278 | healthFrame.strategy = 'UnitClass' | ||
230 | local n = tostring(self:GetName()) | ||
231 | local healthStatusBar = _G[n .. 'HealthStatusBar'] | ||
232 | if healthStatusBar then | ||
233 | healthStatusBar:SetAttribute('chorus-strategy', 'UnitIsFriend') | ||
279 | 234 | end | end |
280 | 235 | end | end |
281 | 236 | ||
... | ... | Chorus.unitFrameMain = function(...) | |
283 | 238 | return unitFrameMain(...) | return unitFrameMain(...) |
284 | 239 | end | end |
285 | 240 | ||
241 | Chorus.unitTOTFrameMain = function(...) | ||
242 | return unitTOTFrameMain(...) | ||
243 | end | ||
244 | |||
286 | 245 | Chorus.unitMemberFrameMain = function(...) | Chorus.unitMemberFrameMain = function(...) |
287 | 246 | return unitMemberFrameMain(...) | return unitMemberFrameMain(...) |
288 | 247 | end | end |
File src/ChorusUnitFrameTemplate.xml changed (mode: 100644) (index ccf6071..7fa2f1f) | |||
22 | 22 | <!-- Target-of-target (TOT) unit frame is updated multiple times a second. Use sparingly. --> | <!-- Target-of-target (TOT) unit frame is updated multiple times a second. Use sparingly. --> |
23 | 23 | <Frame name="ChorusTOTUnitFrameTemplate" inherits="ChorusUnitFrameTemplate" virtual="true" protected="false"> | <Frame name="ChorusTOTUnitFrameTemplate" inherits="ChorusUnitFrameTemplate" virtual="true" protected="false"> |
24 | 24 | <Scripts> | <Scripts> |
25 | <OnLoad>Chorus.unitTOTFrameMain(self);</OnLoad> | ||
25 | 26 | <OnUpdate>Chorus.unitFrameTOTUpdateProcessor(self);</OnUpdate> | <OnUpdate>Chorus.unitFrameTOTUpdateProcessor(self);</OnUpdate> |
26 | 27 | </Scripts> | </Scripts> |
27 | 28 | </Frame> | </Frame> |
File src/ChorusUnitHealthFrameTemplate.lua changed (mode: 100644) (index 68d2cad..6fd966f) | |||
... | ... | local function apply3(label, amountCurrent, amountMax) | |
104 | 104 | label:SetText(s) | label:SetText(s) |
105 | 105 | end | end |
106 | 106 | ||
107 | local function apply(unitHealthFrame, u) | ||
107 | local function applyUnitHealth(unitHealthFrame, u) | ||
108 | 108 | assert(unitHealthFrame ~= nil) | assert(unitHealthFrame ~= nil) |
109 | 109 | ||
110 | 110 | assert(u ~= nil) | assert(u ~= nil) |
... | ... | local function apply(unitHealthFrame, u) | |
129 | 129 | end | end |
130 | 130 | end | end |
131 | 131 | ||
132 | local function eventProcessor(unitHealthFrame, eventCategory, unitDesignation) | ||
132 | local function eventProcessorUnitHealth(unitHealthFrame, eventCategory, unitDesignation) | ||
133 | 133 | assert(unitHealthFrame ~= nil) | assert(unitHealthFrame ~= nil) |
134 | 134 | ||
135 | 135 | local thisUnit = SecureButton_GetUnit(unitHealthFrame) or 'none' | local thisUnit = SecureButton_GetUnit(unitHealthFrame) or 'none' |
... | ... | local function eventProcessor(unitHealthFrame, eventCategory, unitDesignation) | |
149 | 149 | not UnitIsGhost(thisUnit) then | not UnitIsGhost(thisUnit) then |
150 | 150 | ||
151 | 151 | unitHealthFrame:Show() | unitHealthFrame:Show() |
152 | apply(unitHealthFrame, thisUnit) | ||
152 | applyUnitHealth(unitHealthFrame, thisUnit) | ||
153 | 153 | else | else |
154 | 154 | unitHealthFrame:Hide() | unitHealthFrame:Hide() |
155 | 155 | end | end |
156 | 156 | end | end |
157 | 157 | ||
158 | local function main(unitHealthFrame) | ||
158 | local function mainUnitHealth(unitHealthFrame) | ||
159 | 159 | assert(unitHealthFrame ~= nil) | assert(unitHealthFrame ~= nil) |
160 | 160 | ||
161 | 161 | local n = unitHealthFrame:GetName() | local n = unitHealthFrame:GetName() |
... | ... | local function main(unitHealthFrame) | |
172 | 172 | --[[ `label3` displays health deficite amount. ]]-- | --[[ `label3` displays health deficite amount. ]]-- |
173 | 173 | unitHealthFrame.label3 = unitHealthFrame.label3 or _G[n .. 'Text3'] | unitHealthFrame.label3 = unitHealthFrame.label3 or _G[n .. 'Text3'] |
174 | 174 | ||
175 | assert(unitHealthFrame.label1 ~= nil) | ||
176 | assert(unitHealthFrame.label2 ~= nil) | ||
177 | assert(unitHealthFrame.label3 ~= nil) | ||
175 | assert(unitHealthFrame.label1 ~= nil | ||
176 | or unitHealthFrame.label2 ~= nil | ||
177 | or unitHealthFrame.label3 ~= nil) | ||
178 | 178 | ||
179 | 179 | unitHealthFrame:UnregisterAllEvents() | unitHealthFrame:UnregisterAllEvents() |
180 | 180 | ||
... | ... | local function main(unitHealthFrame) | |
189 | 189 | unitHealthFrame:RegisterEvent('RAID_ROSTER_UPDATE') | unitHealthFrame:RegisterEvent('RAID_ROSTER_UPDATE') |
190 | 190 | unitHealthFrame:RegisterEvent('UNIT_HEALTH') | unitHealthFrame:RegisterEvent('UNIT_HEALTH') |
191 | 191 | ||
192 | unitHealthFrame:SetScript('OnEvent', eventProcessor) | ||
192 | unitHealthFrame:SetScript('OnEvent', eventProcessorUnitHealth) | ||
193 | end | ||
194 | |||
195 | local function applyUnitPower(unitPowerFrame, u) | ||
196 | assert(unitPowerFrame ~= nil) | ||
197 | |||
198 | assert(u ~= nil) | ||
199 | |||
200 | local label1 = unitPowerFrame.label1 | ||
201 | local label2 = unitPowerFrame.label2 | ||
202 | assert(label1 ~= nil or label2 ~= nil, | ||
203 | 'invalid state: at least one label must exist for unit power frame') | ||
204 | |||
205 | local powerTypeIndex = unitPowerFrame:GetAttribute('chorus-unitpowertype') or UnitPowerType(u) | ||
206 | --[[ Skip validation since this function is called frequently. ]]-- | ||
207 | |||
208 | local a = UnitPower(u, powerTypeIndex) | ||
209 | local b = UnitPowerMax(u, powerTypeIndex) | ||
210 | |||
211 | if label1 then | ||
212 | apply1(label1, a, b) | ||
213 | end | ||
214 | if label2 then | ||
215 | apply2(label2, a) | ||
216 | end | ||
217 | end | ||
218 | |||
219 | local function eventProcessorUnitPower(unitPowerFrame, eventCategory, unitDesignation) | ||
220 | assert(unitPowerFrame ~= nil) | ||
221 | assert(eventCategory ~= nil) | ||
222 | |||
223 | local thisUnit = SecureButton_GetUnit(unitPowerFrame) or 'none' | ||
224 | assert(thisUnit ~= nil) | ||
225 | |||
226 | if unitDesignation and not UnitIsUnit(unitDesignation, thisUnit) then | ||
227 | return | ||
228 | end | ||
229 | |||
230 | if UnitExists(thisUnit) and | ||
231 | UnitIsConnected(thisUnit) and | ||
232 | not UnitIsDead(thisUnit) and | ||
233 | not UnitIsCorpse(thisUnit) and | ||
234 | not UnitIsGhost(thisUnit) then | ||
235 | |||
236 | unitPowerFrame:Show() | ||
237 | applyUnitPower(unitPowerFrame, thisUnit) | ||
238 | else | ||
239 | unitPowerFrame:Hide() | ||
240 | end | ||
241 | end | ||
242 | |||
243 | local function mainUnitPower(unitPowerFrame) | ||
244 | assert(unitPowerFrame ~= nil) | ||
245 | |||
246 | local n = unitPowerFrame:GetName() | ||
247 | assert(n ~= nil) | ||
248 | assert('string' == type(n)) | ||
249 | n = strtrim(n) | ||
250 | assert(string.len(n) >= 1) | ||
251 | assert(string.len(n) <= 256) | ||
252 | |||
253 | --[[ `label1` displays mana percentage. ]]-- | ||
254 | unitPowerFrame.label1 = unitPowerFrame.label1 or _G[n .. 'Text1'] | ||
255 | --[[ `label2` displays mana amount. ]]-- | ||
256 | unitPowerFrame.label2 = unitPowerFrame.label2 or _G[n .. 'Text2'] | ||
257 | |||
258 | assert(unitPowerFrame.label1 ~= nil) | ||
259 | assert(unitPowerFrame.label2 ~= nil) | ||
260 | |||
261 | unitPowerFrame:UnregisterAllEvents() | ||
262 | |||
263 | unitPowerFrame:RegisterEvent('PARTY_CONVERTED_TO_RAID') | ||
264 | unitPowerFrame:RegisterEvent('PARTY_MEMBERS_CHANGED') | ||
265 | unitPowerFrame:RegisterEvent('PARTY_MEMBER_DISABLE') | ||
266 | unitPowerFrame:RegisterEvent('PARTY_MEMBER_ENABLE') | ||
267 | unitPowerFrame:RegisterEvent('PLAYER_ALIVE') | ||
268 | unitPowerFrame:RegisterEvent('PLAYER_FOCUS_CHANGED') | ||
269 | unitPowerFrame:RegisterEvent('PLAYER_LOGIN') | ||
270 | unitPowerFrame:RegisterEvent('PLAYER_TARGET_CHANGED') | ||
271 | unitPowerFrame:RegisterEvent('RAID_ROSTER_UPDATE') | ||
272 | |||
273 | unitPowerFrame:RegisterEvent('UNIT_ENERGY') | ||
274 | unitPowerFrame:RegisterEvent('UNIT_MANA') | ||
275 | unitPowerFrame:RegisterEvent('UNIT_MAXPOWER') | ||
276 | unitPowerFrame:RegisterEvent('UNIT_POWER') | ||
277 | unitPowerFrame:RegisterEvent('UNIT_RAGE') | ||
278 | unitPowerFrame:RegisterEvent('UNIT_RUNIC_POWER') | ||
279 | |||
280 | unitPowerFrame:SetScript('OnEvent', eventProcessorUnitPower) | ||
193 | 281 | end | end |
194 | 282 | ||
195 | 283 | Chorus.unitHealthFrameMain = function(...) | Chorus.unitHealthFrameMain = function(...) |
196 | return main(...) | ||
284 | return mainUnitHealth(...) | ||
285 | end | ||
286 | |||
287 | Chorus.unitPowerFrameMain = function(...) | ||
288 | return mainUnitPower(...) | ||
197 | 289 | end | end |
File src/ChorusUnitHealthStatusBarTemplate.lua changed (mode: 100644) (index 30adf3d..126f822) | |||
... | ... | event, and `false` if it should abort | |
57 | 57 | local function eventUnitFilter(thisUnit, eventCategory, eventUnit) | local function eventUnitFilter(thisUnit, eventCategory, eventUnit) |
58 | 58 | eventCategory = tostring(eventCategory) | eventCategory = tostring(eventCategory) |
59 | 59 | ||
60 | --[[-- @fixme Trigger for PLAYER_TARGET_CHANGED does not work properly. | ||
61 | There is a logic error. TOT frames linger like this when unit does not | ||
62 | exist. | ||
63 | ]] | ||
64 | |||
60 | 65 | if 'UNIT_HEALTH' == eventCategory then | if 'UNIT_HEALTH' == eventCategory then |
61 | 66 | return UnitIsUnit(eventUnit, thisUnit) | return UnitIsUnit(eventUnit, thisUnit) |
62 | elseif 'PLAYER_TARGET_CHANGED' == eventCategory then | ||
63 | return UnitIsUnit('target', thisUnit) | ||
64 | elseif 'PLAYER_FOCUS_CHANGED' == eventCategory then | ||
65 | return UnitIsUnit('focus', thisUnit) | ||
67 | --elseif 'PLAYER_TARGET_CHANGED' == eventCategory then | ||
68 | --return UnitIsUnit('target', thisUnit) | ||
69 | --elseif 'PLAYER_FOCUS_CHANGED' == eventCategory then | ||
70 | --return UnitIsUnit('focus', thisUnit) | ||
66 | 71 | elseif 'UNIT_THREAT_SITUATION_UPDATE' == eventCategory then | elseif 'UNIT_THREAT_SITUATION_UPDATE' == eventCategory then |
67 | 72 | return UnitIsUnit(eventUnit, thisUnit) | return UnitIsUnit(eventUnit, thisUnit) |
68 | 73 | end | end |
File src/ChorusUnitHealthStatusBarTemplate.xml changed (mode: 100644) (index bea66f0..b94dd38) | |||
6 | 6 | <Size> | <Size> |
7 | 7 | <AbsDimension x="144" y="24"/> | <AbsDimension x="144" y="24"/> |
8 | 8 | </Size> | </Size> |
9 | <Layers> | ||
10 | <Layer level="BACKGROUND"> | ||
11 | <Texture name="$parentBackground" nonBlocking="true" setAllPoints="true"> | ||
12 | <Color r="0" g="0" b="0" a="0.4"/> | ||
13 | </Texture> | ||
14 | </Layer> | ||
15 | </Layers> | ||
16 | 9 | <Scripts> | <Scripts> |
17 | 10 | <OnLoad>Chorus.unitHealthStatusBarMain(self);</OnLoad> | <OnLoad>Chorus.unitHealthStatusBarMain(self);</OnLoad> |
18 | 11 | <OnAttributeChanged>Chorus.unitHealthStatusBarAttributeProcessor(self, name, value);</OnAttributeChanged> | <OnAttributeChanged>Chorus.unitHealthStatusBarAttributeProcessor(self, name, value);</OnAttributeChanged> |
59 | 52 | <Attribute name="chorus-strategy" type="string" value="LowHealth"/> | <Attribute name="chorus-strategy" type="string" value="LowHealth"/> |
60 | 53 | </Attributes> | </Attributes> |
61 | 54 | </StatusBar> | </StatusBar> |
62 | <!-- FIXME Remove test unit health status bar. --> | ||
63 | <StatusBar name="ChorusTest13" inherits="ChorusUnitHealthUnitClassStatusBarTemplate"> | ||
64 | <Anchors> | ||
65 | <Anchor point="BOTTOMLEFT"> | ||
66 | <Offset x="300" y="300"/> | ||
67 | </Anchor> | ||
68 | </Anchors> | ||
69 | <Attributes> | ||
70 | <Attribute name="unit" type="string" value="player"/> | ||
71 | </Attributes> | ||
72 | </StatusBar> | ||
73 | <Frame name="ChorusTest16" inherits="ChorusUnitHealthHugeFrameTemplate"> | ||
74 | <Anchors> | ||
75 | <Anchor point="BOTTOMLEFT"> | ||
76 | <Offset x="300" y="300"/> | ||
77 | </Anchor> | ||
78 | </Anchors> | ||
79 | <Attributes> | ||
80 | <Attribute name="unit" type="string" value="player"/> | ||
81 | </Attributes> | ||
82 | </Frame> | ||
83 | <StatusBar name="ChorusTest14" inherits="ChorusUnitHealthLowHealthStatusBarTemplate"> | ||
84 | <Anchors> | ||
85 | <Anchor point="BOTTOMLEFT"> | ||
86 | <Offset x="500" y="300"/> | ||
87 | </Anchor> | ||
88 | </Anchors> | ||
89 | <Attributes> | ||
90 | <Attribute name="unit" type="string" value="target"/> | ||
91 | </Attributes> | ||
92 | </StatusBar> | ||
93 | <Frame name="ChorusTest17" inherits="ChorusUnitHealthHugeFrameTemplate"> | ||
94 | <Anchors> | ||
95 | <Anchor point="BOTTOMLEFT"> | ||
96 | <Offset x="500" y="300"/> | ||
97 | </Anchor> | ||
98 | </Anchors> | ||
99 | <Attributes> | ||
100 | <Attribute name="unit" type="string" value="target"/> | ||
101 | </Attributes> | ||
102 | </Frame> | ||
103 | <Frame name="ChorusVakh"> | ||
104 | <Size> | ||
105 | <AbsDimension x="300" y="200"/> | ||
106 | </Size> | ||
107 | <Anchors> | ||
108 | <Anchor point="BOTTOMLEFT"> | ||
109 | <Offset x="300" y="400"/> | ||
110 | </Anchor> | ||
111 | </Anchors> | ||
112 | <Frames> | ||
113 | <StatusBar name="ChorusTest15" inherits="ChorusUnitHealthLowHealthStatusBarTemplate"> | ||
114 | <Anchors> | ||
115 | <Anchor point="BOTTOMLEFT"> | ||
116 | <Offset x="0" y="0"/> | ||
117 | </Anchor> | ||
118 | </Anchors> | ||
119 | <Attributes> | ||
120 | <Attribute name="unit" type="string" value="target"/> | ||
121 | </Attributes> | ||
122 | </StatusBar> | ||
123 | </Frames> | ||
124 | <Attributes> | ||
125 | <Attribute name="chorus-strategy" type="string" value="UnitClass"/> | ||
126 | </Attributes> | ||
127 | </Frame> | ||
128 | 55 | </Ui> | </Ui> |
File src/ChorusUnitPowerFrameTemplate.xml added (mode: 100644) (index 0000000..cb1c837) | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <Ui xmlns="http://www.blizzard.com/wow/ui/"> | ||
3 | <!-- See `ChorusUnitHealthFrameTemplate.lua`. | ||
4 | All event processors for unit power label frames are defined there, | ||
5 | to avoid duplicating code. --> | ||
6 | <Frame name="ChorusUnitPowerFrameTemplate" virtual="true"> | ||
7 | <Size> | ||
8 | <AbsDimension x="144" y="24"/> | ||
9 | </Size> | ||
10 | <Attributes> | ||
11 | <Attribute name="useparent-unit" type="boolean" value="true"/> | ||
12 | </Attributes> | ||
13 | <Scripts> | ||
14 | <OnLoad>Chorus.unitPowerFrameMain(self);</OnLoad> | ||
15 | </Scripts> | ||
16 | </Frame> | ||
17 | <Frame name="ChorusUnitPowerLargeFrameTemplate" inherits="ChorusUnitPowerFrameTemplate" virtual="true"> | ||
18 | <Layers> | ||
19 | <Layer level="OVERLAY"> | ||
20 | <FontString name="$parentText1" inherits="ChorusFont12Mono" justifyH="LEFT" justifyV="MIDDLE" setAllPoints="true"/> | ||
21 | <FontString name="$parentText2" inherits="ChorusFont12Mono" justifyH="RIGHT" justifyV="MIDDLE" setAllPoints="true"/> | ||
22 | </Layer> | ||
23 | </Layers> | ||
24 | </Frame> | ||
25 | <Frame name="ChorusUnitPowerSmallFrameTemplate" inherits="ChorusUnitPowerFrameTemplate" virtual="true"> | ||
26 | <Layers> | ||
27 | <Layer level="OVERLAY"> | ||
28 | <FontString name="$parentText1" inherits="ChorusFont12Mono" justifyH="LEFT" justifyV="MIDDLE" setAllPoints="true"/> | ||
29 | </Layer> | ||
30 | </Layers> | ||
31 | </Frame> | ||
32 | </Ui> |
File src/ChorusUnitPowerStatusBarTemplate.lua added (mode: 100644) (index 0000000..1f2a061) | |||
1 | --[[-- | ||
2 | @submodule chorus | ||
3 | ]] | ||
4 | |||
5 | --[[ See `FrameXML/UnitFrame.lua:PowerBarColor`. ]]-- | ||
6 | local PowerBarColor = PowerBarColor | ||
7 | |||
8 | local Chorus = Chorus | ||
9 | |||
10 | local function setColor(statusBar, r, g, b) | ||
11 | assert(statusBar ~= nil) | ||
12 | |||
13 | local artwork = statusBar.artwork | ||
14 | assert(artwork ~= nil) | ||
15 | |||
16 | local image = artwork:GetTexture() | ||
17 | if image then | ||
18 | artwork:SetVertexColor(r, g, b) | ||
19 | else | ||
20 | artwork:SetTexture(r, g, b) | ||
21 | end | ||
22 | end | ||
23 | |||
24 | local function apply(unitPowerStatusBar, u, powerTypeIndex) | ||
25 | assert(unitPowerStatusBar ~= nil) | ||
26 | |||
27 | local a = UnitPower(u, powerTypeIndex) | ||
28 | local b = UnitPowerMax(u, powerTypeIndex) | ||
29 | |||
30 | unitPowerStatusBar:SetMinMaxValues(0, b) | ||
31 | unitPowerStatusBar:SetValue(a) | ||
32 | end | ||
33 | |||
34 | local function applyColor(unitPowerStatusBar, powerTypeIndex) | ||
35 | local d = PowerBarColor[powerTypeIndex] | ||
36 | setColor(unitPowerStatusBar, d.r, d.g, d.b) | ||
37 | end | ||
38 | |||
39 | local function eventProcessor(unitPowerStatusBar, eventCategory, unitDesignation) | ||
40 | assert(unitPowerStatusBar ~= nil) | ||
41 | |||
42 | eventCategory = tostring(eventCategory) | ||
43 | |||
44 | local thisUnit = SecureButton_GetUnit(unitPowerStatusBar) | ||
45 | if unitDesignation and not UnitIsUnit(thisUnit, unitDesignation) then | ||
46 | return | ||
47 | end | ||
48 | |||
49 | if UnitExists(thisUnit) and UnitIsConnected(thisUnit) then | ||
50 | unitPowerStatusBar:Show() | ||
51 | else | ||
52 | unitPowerStatusBar:Hide() | ||
53 | return | ||
54 | end | ||
55 | |||
56 | local powerTypeIndex = unitPowerStatusBar:GetAttribute('chorus-unitpowertype') or UnitPowerType(thisUnit) | ||
57 | --[[ Skip validation since this function is called frequently. ]]-- | ||
58 | |||
59 | apply(unitPowerStatusBar, thisUnit, powerTypeIndex) | ||
60 | if 'UNIT' == string.sub(eventCategory, 1, 4) then | ||
61 | return | ||
62 | end | ||
63 | |||
64 | if 'PLAYER_TARGET_CHANGED' == eventCategory and UnitIsUnit('target', thisUnit) then | ||
65 | applyColor(unitPowerStatusBar, powerTypeIndex) | ||
66 | elseif 'PLAYER_FOCUS_CHANGED' == eventCategory and UnitIsUnit('focus', thisUnit) then | ||
67 | applyColor(unitPowerStatusBar, powerTypeIndex) | ||
68 | else | ||
69 | applyColor(unitPowerStatusBar, powerTypeIndex) | ||
70 | end | ||
71 | end | ||
72 | |||
73 | local function attributeProcessor(unitPowerStatusBar, name) | ||
74 | if name == 'chorus-unitpowertype' then | ||
75 | eventProcessor(unitPowerStatusBar) | ||
76 | end | ||
77 | end | ||
78 | |||
79 | local function main(unitPowerStatusBar) | ||
80 | assert(unitPowerStatusBar ~= nil) | ||
81 | |||
82 | local n = unitPowerStatusBar:GetName() | ||
83 | assert(n ~= nil) | ||
84 | n = tostring(n) | ||
85 | |||
86 | unitPowerStatusBar.artwork = _G[n .. 'Artwork'] | ||
87 | |||
88 | unitPowerStatusBar:UnregisterAllEvents() | ||
89 | |||
90 | unitPowerStatusBar:RegisterEvent('PARTY_CONVERTED_TO_RAID') | ||
91 | unitPowerStatusBar:RegisterEvent('PARTY_MEMBERS_CHANGED') | ||
92 | unitPowerStatusBar:RegisterEvent('PARTY_MEMBER_DISABLE') | ||
93 | unitPowerStatusBar:RegisterEvent('PARTY_MEMBER_ENABLE') | ||
94 | unitPowerStatusBar:RegisterEvent('PLAYER_ALIVE') | ||
95 | unitPowerStatusBar:RegisterEvent('PLAYER_FOCUS_CHANGED') | ||
96 | unitPowerStatusBar:RegisterEvent('PLAYER_LOGIN') | ||
97 | unitPowerStatusBar:RegisterEvent('PLAYER_TARGET_CHANGED') | ||
98 | unitPowerStatusBar:RegisterEvent('RAID_ROSTER_UPDATE') | ||
99 | |||
100 | unitPowerStatusBar:RegisterEvent('UNIT_ENERGY') | ||
101 | unitPowerStatusBar:RegisterEvent('UNIT_MANA') | ||
102 | unitPowerStatusBar:RegisterEvent('UNIT_MAXPOWER') | ||
103 | unitPowerStatusBar:RegisterEvent('UNIT_POWER') | ||
104 | unitPowerStatusBar:RegisterEvent('UNIT_RAGE') | ||
105 | unitPowerStatusBar:RegisterEvent('UNIT_RUNIC_POWER') | ||
106 | |||
107 | unitPowerStatusBar:SetScript('OnEvent', eventProcessor) | ||
108 | unitPowerStatusBar:SetScript('OnAttributeChanged', attributeProcessor) | ||
109 | end | ||
110 | |||
111 | Chorus.unitPowerStatusBarMain = function(...) | ||
112 | return main(...) | ||
113 | end |
File src/ChorusUnitPowerStatusBarTemplate.xml added (mode: 100644) (index 0000000..931433c) | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <Ui xmlns="http://www.blizzard.com/wow/ui/"> | ||
3 | <Script file="ChorusUnitPowerStatusBarTemplate.lua"/> | ||
4 | <!-- Base health status bar template. It's further specialized by different strategies. --> | ||
5 | <StatusBar name="ChorusUnitPowerStatusBarTemplate" minValue="0" maxValue="1" defaultValue="1" virtual="true"> | ||
6 | <Size> | ||
7 | <AbsDimension x="144" y="24"/> | ||
8 | </Size> | ||
9 | <Scripts> | ||
10 | <OnLoad>Chorus.unitPowerStatusBarMain(self);</OnLoad> | ||
11 | </Scripts> | ||
12 | <Attributes> | ||
13 | <Attribute name="useparent-unit" type="boolean" value="true"/> | ||
14 | </Attributes> | ||
15 | <BarTexture name="$parentArtwork" file="Interface\TargetingFrame\UI-StatusBar"/> | ||
16 | <BarColor r="1" g="0" b="1" a="1"/> | ||
17 | </StatusBar> | ||
18 | </Ui> |