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!: remove all taint from aura buttons 198dcbb367596370de36e6ebbcde3c9a1887b657 Vladyslav Bondarenko 2024-07-14 23:21:37
fix: show death knight rune frame at player frame 9949a0bafac5d0f1ccbcd3f80b301977d4fa4e0f Vladyslav Bondarenko 2024-07-14 15:46:33
feat: prepare release 0.10.0 7b12ee714c95d94d9d34dd034fe7c1b27b29fa0e Vladyslav Bondarenko 2024-06-27 12:54:18
fix: raid profile toggle robustness 9cba01bac77db4d383c159136f904fec00f57d43 Vladyslav Bondarenko 2024-06-25 07:11:38
fix: cast bar update robustness e2e7910e0d96eb65aea9a2a3337fa50cecccc45f Vladyslav Bondarenko 2024-06-25 07:11:07
fix!: toggle raid frame 59503ee6ec8744f057e959c026cacb0e39ee62db Vladyslav Bondarenko 2024-06-23 07:58:42
feat!: prepare release 0.9.0 6b15c2a4567dae6b363d69fa84348aa2dbca7b74 Vladyslav Bondarenko 2024-06-18 22:41:56
fix: add UnitIsTapped to known globals list 9536f6ae6bb9f2e4ce1a668f3a55c2ad0a225cb7 Vladyslav Bondarenko 2024-06-18 22:40:45
feat: upgrade cast bar f050d4444480983bfe7475bdafbfeb2c291c3472 Vladyslav Bondarenko 2024-06-18 18:11:20
fix!: only update cast bar when it's visible 7c2081b92a1ec323911520a977c00f68078bae18 Vladyslav Bondarenko 2024-06-18 17:09:56
fix: cast bar always reports ongoing cast d69d60f524a7871053daa2d914badc59e1189e15 Vladyslav Bondarenko 2024-06-18 15:37:59
feat: color unit headers by reaction af87ae82144ba3e49bec3f3cc18919b502d46da8 Vladyslav Bondarenko 2024-06-18 15:19:21
feat: weigh priest effects 99341dd5c6cb03861fdfa802a1cde520887b29b5 Vladyslav Bondarenko 2024-06-18 14:01:45
feat: make cast bar prettier visually 8ef25268de9a70ce741f0e9b4c105d4969afe7ff Vladyslav Bondarenko 2024-06-18 14:01:03
doc: show todo and fixme annotations in the docs a880f593e674df82682c295375319b7a4cf13b20 Vladyslav Bondarenko 2024-06-18 11:58:53
fix: make raid frames protected c94bb2d05a404e2a1e802cf03daa6325cf38827b Vladyslav Bondarenko 2024-06-18 11:57:42
feat: cast bar shows instants and failures c08b3be1c0d8d63b298a71ddf7af734703ffcb42 Vladyslav Bondarenko 2024-06-16 20:42:42
feat: spell channel bar moves in reverse 64e0512304854e28df8ad94363a048fd997dc502 Vladyslav Bondarenko 2024-06-16 19:19:53
doc: valid references to github 6aba3821b71216c07d8f02b24f75006e556dca61 Vladyslav Bondarenko 2024-06-16 17:28:59
build: allow either GNUmake or pdpmake to be used 4f3cd088299dc09f5207caeeddedfcca461d439e Vladyslav Bondarenko 2024-06-16 15:52:32
Commit 198dcbb367596370de36e6ebbcde3c9a1887b657 - fix!: remove all taint from aura buttons
Ensure that dialog menu that warns about forbidden actions performed by
the add-on never appears. Aura buttons do not appear in the taint log.

WARNING: There is an issue with no longer needed debuffs lingering.
Author: Vladyslav Bondarenko
Author date (UTC): 2024-07-14 23:21
Committer name: Vladyslav Bondarenko
Committer date (UTC): 2024-07-14 23:21
Parent(s): 9949a0bafac5d0f1ccbcd3f80b301977d4fa4e0f
Signer:
Signing key: EFF9624877D25D02
Signing status: E
Tree: 343f0b067f259217af87455eb6ccba907d8af987
File Lines added Lines deleted
src/ChorusAuraButtonTemplate.lua 117 45
src/ChorusAuraFrameTemplate.lua 15 12
File src/ChorusAuraButtonTemplate.lua changed (mode: 100644) (index 0fb5a03..261627e)
... ... local function applyOverlay(auraButton, category, owner)
117 117
118 118 overlay:SetVertexColor(r, g, b) overlay:SetVertexColor(r, g, b)
119 119
120 --[[ ShadowedUnitFrames recommend this approach for adjusting font size. ]]--
121 120 local label = auraButton.label local label = auraButton.label
122 121 assert(label ~= nil) assert(label ~= nil)
123 local t = label:GetText()
124 if t ~= nil and string.len(t) >= 1 then
125 local fontSize = 12
126 auraButton:SetScale(label:GetStringHeight() / fontSize)
127 end
128
129 122 if owner and 'player' == owner then if owner and 'player' == owner then
130 123 label:SetTextColor(1, 225 / 255, 0) label:SetTextColor(1, 225 / 255, 0)
131 124 else else
132 125 label:SetTextColor(1, 1, 1) label:SetTextColor(1, 1, 1)
133 126 end end
127 overlay:SetAlpha(1)
134 128 end end
135 129
136 130 --[[-- --[[--
 
... ... processor function.
277 271 @return nothing @return nothing
278 272 ]] ]]
279 273 local function auraButtonUpdateProcessor(self) local function auraButtonUpdateProcessor(self)
280 local unitDesignation = SecureButton_GetUnit(self)
274 --[[-- @warning This function is executed every frame for every unit
275 aura button. It must be optimized as much as possible.]]
276
277 --[[-- It is not throttled for the sake of accuracy. Maybe it should
278 be. ]]
279
281 280 local index = self.index local index = self.index
281 if not index then
282 return
283 end
284
285 local unitDesignation = SecureButton_GetUnit(self)
286 if not unitDesignation then
287 return
288 end
289
282 290 local filter = SecureButton_GetAttribute(self, 'filter') local filter = SecureButton_GetAttribute(self, 'filter')
283 if not unitDesignation or not index then
291 if not filter then
284 292 return return
285 293 end end
294
286 295 local name, _, _, chargeQuantity, _, durationSec, expirationInstance = UnitAura(unitDesignation, index, filter) local name, _, _, chargeQuantity, _, durationSec, expirationInstance = UnitAura(unitDesignation, index, filter)
287 296 if not name then if not name then
288 297 return return
 
... ... local function auraButtonUpdateProcessor(self)
291 300 applyChargeQuantity(self, chargeQuantity) applyChargeQuantity(self, chargeQuantity)
292 301 end end
293 302
303 --[[--
304 Obscure the aura button to the user's eye, without toggling frame visibility
305 mechanically.
306
307 Toggling visibility of a frame is a restricted action. That is, it can only be
308 done in combat by trusted or secure frames. The aura buttons, for the sake of
309 their core features, are not secure or trusted frames. Therefore, they must
310 never be toggled with `Show` or `Hide` frame methods.
311
312 This implementation must also leave to traces in the taint log.
313 (Logs/taint.log)
314
315 @see InCombatLockdown
316 @see issecure
317
318 @function unapply
319 @tparam frame auraButton this aura button
320 @return nothing, only side effects
321 ]]
322 local function unapply(auraButton)
323 assert(auraButton ~= nil)
324
325 auraButton.index = nil
326 auraButton.spell = nil
327
328 local artwork = auraButton.artwork
329 assert(artwork ~= nil)
330 artwork:SetTexture(artworkFile)
331 artwork:SetAlpha(1)
332
333 --[[ Remaining duration ]]--
334 local label = auraButton.label
335 assert (label ~= nil)
336 label:SetText(nil)
337
338 --[[ Remaining charge quantity ]]--
339 local label2 = auraButton.label2
340 assert (label2 ~= nil)
341 label2:SetText(nil)
342
343 local overlay = auraButton.overlay
344 assert(overlay ~= nil)
345 overlay:SetAlpha(0)
346 end
347
294 348 --[[-- --[[--
295 349 Request relevant aura details, then apply them to the aura button. Request relevant aura details, then apply them to the aura button.
296 350
 
... ... local function apply(auraButton, unitDesignation, auraIndex, filter)
328 382 assert(string.len(filter) >= 1) assert(string.len(filter) >= 1)
329 383 assert(string.len(filter) <= 256) assert(string.len(filter) <= 256)
330 384
331 --[[ @warning Aura button event processor might fail in restricted
332 environment. ]]--
333
334 385 if not UnitExists(unitDesignation) or not UnitIsConnected(unitDesignation) then if not UnitExists(unitDesignation) or not UnitIsConnected(unitDesignation) then
335 auraButton:Hide()
336 auraButton:SetScript('OnUpdate', nil)
386 unapply(auraButton)
337 387 return return
338 388 end end
339 389
340 390 local name, _, artworkFile, chargeQuantity, category, durationSec, expirationInstance, local name, _, artworkFile, chargeQuantity, category, durationSec, expirationInstance,
341 391 owner = UnitAura(unitDesignation, auraIndex, filter) owner = UnitAura(unitDesignation, auraIndex, filter)
342 if name then
343 auraButton:Show()
344 auraButton:SetScript('OnUpdate', auraButtonUpdateProcessor)
345 else
346 auraButton:Hide()
347 auraButton:SetScript('OnUpdate', nil)
392 if not name then
393 unapply(auraButton)
348 394 return return
349 395 end end
350 396
 
... ... watch that unit, then apply relevant changes to the aura button.
371 417 function Chorus.auraButtonEventProcessor(self, eventCategory, ...) function Chorus.auraButtonEventProcessor(self, eventCategory, ...)
372 418 auraButtonValidate(self) auraButtonValidate(self)
373 419
374 local u = SecureButton_GetUnit(self) or 'none'
375 assert(u ~= nil)
376 assert('string' == type(u))
377 u = string.lower(strtrim(u))
378 assert(string.len(u) >= 1)
379 assert(string.len(u) <= 256)
420 local thisUnit = SecureButton_GetUnit(self) or 'none'
421 assert(thisUnit ~= nil)
422 assert('string' == type(thisUnit))
423 thisUnit = string.lower(strtrim(thisUnit))
424 assert(string.len(thisUnit) >= 1)
425 assert(string.len(thisUnit) <= 256)
426
427 assert(eventCategory ~= nil)
428 assert('string' == type(eventCategory))
429 eventCategory = string.upper(strtrim(eventCategory))
430 assert(string.len(eventCategory) >= 1)
431 assert(string.len(eventCategory) <= 256)
380 432
381 --[[ Break if unit doesn't exist. ]]--
382 if UnitExists(u) and UnitIsConnected(u) then
383 self:Show()
384 else
385 self:Hide()
386 return
387 end
388 433
389 --[[ Break if event is not relevant to this button. ]]--
390 if eventCategory then
391 assert(eventCategory ~= nil)
392 assert('string' == type(eventCategory))
393 eventCategory = string.upper(strtrim(eventCategory))
394 assert(string.len(eventCategory) >= 1)
395 assert(string.len(eventCategory) <= 256)
396
397 local o = select(1, ...)
398 if eventCategory == 'UNIT_AURA' and o and not UnitIsUnit(u, o) then
399 self:Hide()
434 if 'ADDON_LOADED' == tostring(eventCategory) then
435 --[[-- @warning Hardcoded addon name here.
436 ]]
437
438 local loadedAddonName = select(1, ...)
439 local thisAddonName = 'chorus'
440 if thisAddonName ~= tostring(loadedAddonName) then
441 return
442 end
443 elseif 'UNIT_AURA' == tostring(eventCategory) then
444 local otherUnit = select(1, ...)
445 if not UnitIsUnit(thisUnit, otherUnit) then
400 446 return return
401 447 end end
402 448 end end
403 449
450 if not UnitExists(thisUnit) or not UnitIsConnected(thisUnit) then
451 unapply(self)
452 return
453 end
454
404 455 --[[ Do work. ]]-- --[[ Do work. ]]--
405 456 local i = self.index or 0 local i = self.index or 0
406 457 assert(i ~= nil) assert(i ~= nil)
 
... ... function Chorus.auraButtonEventProcessor(self, eventCategory, ...)
414 465 assert(string.len(filter) >= 1) assert(string.len(filter) >= 1)
415 466 assert(string.len(filter) <= 256) assert(string.len(filter) <= 256)
416 467
417 apply(self, u, i, filter)
468 apply(self, thisUnit, i, filter)
418 469 end end
419 470
420 471 --[[-- --[[--
 
... ... function Chorus.auraButtonGameTooltipHide()
455 506 GameTooltip:Hide(); GameTooltip:Hide();
456 507 end end
457 508
509 local function auraButtonTextScale(auraButton)
510 assert(auraButton ~= nil)
511
512 --[[ ShadowedUnitFrames recommend this approach for adjusting font
513 size. ]]--
514
515 --[[ Only do this at initialization to save on processing and prevent
516 visual flicker. ]]--
517
518 local label = auraButton.label
519 assert(label ~= nil)
520 local t = label:GetText()
521 if t ~= nil and string.len(t) >= 1 then
522 local fontSize = 12
523 auraButton:SetScale(label:GetStringHeight() / fontSize)
524 end
525 end
526
458 527 --[[-- --[[--
459 528 Initialize the aura button frame with callbacks and children. Initialize the aura button frame with callbacks and children.
460 529
 
... ... function Chorus.auraButtonMain(self)
471 540 self.overlay = _G[n .. 'Overlay'] self.overlay = _G[n .. 'Overlay']
472 541 end end
473 542 self:SetScript('OnEvent', Chorus.auraButtonEventProcessor) self:SetScript('OnEvent', Chorus.auraButtonEventProcessor)
543 self:SetScript('OnUpdate', auraButtonUpdateProcessor)
474 544 self:RegisterEvent('ADDON_LOADED') self:RegisterEvent('ADDON_LOADED')
475 545 self:RegisterEvent('UNIT_AURA') self:RegisterEvent('UNIT_AURA')
476 546 auraButtonValidate(self) auraButtonValidate(self)
547
548 auraButtonTextScale(self)
477 549 end end
File src/ChorusAuraFrameTemplate.lua changed (mode: 100644) (index 11fd547..25ea6da)
... ... end
85 85 local function auraFrameEventProcessor(self, eventCategory, ...) local function auraFrameEventProcessor(self, eventCategory, ...)
86 86 assert(self ~= nil) assert(self ~= nil)
87 87
88 --[[ Optimization hack ]]--
89 --[[ Make it use table value if it lags again. ]]--
90 88 local unitDesignation = SecureButton_GetUnit(self) or 'none' local unitDesignation = SecureButton_GetUnit(self) or 'none'
91 89 assert(unitDesignation ~= nil) assert(unitDesignation ~= nil)
92 90 assert('string' == type(unitDesignation)) assert('string' == type(unitDesignation))
 
... ... local function auraFrameEventProcessor(self, eventCategory, ...)
94 92 assert(string.len(unitDesignation) >= 1) assert(string.len(unitDesignation) >= 1)
95 93 assert(string.len(unitDesignation) <= 256) assert(string.len(unitDesignation) <= 256)
96 94
97 if UnitExists(unitDesignation) and UnitIsConnected(unitDesignation) then
98 self:Show()
99 else
100 self:Hide()
101 return
102 end
95 --[[-- @fixme Taint here.
96 ]]
103 97
104 if 'UNIT_AURA' == eventCategory then
98 if 'UNIT_AURA' == tostring(eventCategory) then
105 99 local u = select(1, ...) local u = select(1, ...)
106 if u and 'string' == type(u) and unitDesignation ~= u then
100 if not UnitIsUnit(unitDesignation, u) then
101 return
102 end
103 elseif 'PLAYER_FOCUS_CHANGED' == tostring(eventCategory) then
104 if not UnitIsUnit(unitDesignation, 'focus') then
105 return
106 end
107 elseif 'PLAYER_TARGET_CHANGED' == tostring(eventCategory) then
108 if not UnitIsUnit(unitDesignation, 'target') then
107 109 return return
108 110 end end
109 111 end end
110 112
111 --[[ Make it use table value if it lags again. ]]--
113 assert(eventCategory ~= nil)
114
112 115 local filter = SecureButton_GetAttribute(self, 'filter') local filter = SecureButton_GetAttribute(self, 'filter')
113 116 assert(filter ~= nil) assert(filter ~= nil)
114 117 assert('string' == type(filter)) assert('string' == type(filter))
 
... ... function Chorus.auraFrameMain(self)
239 242 self.filter = SecureButton_GetAttribute(self, 'filter') self.filter = SecureButton_GetAttribute(self, 'filter')
240 243
241 244 self:SetScript('OnEvent', auraFrameEventProcessor) self:SetScript('OnEvent', auraFrameEventProcessor)
242 self:SetScript('OnShow', auraFrameEventProcessor)
245 --self:SetScript('OnShow', auraFrameEventProcessor)
243 246
244 247 if auraWeightMap then if auraWeightMap then
245 248 validateAuraWeightMap(auraWeightMap) validateAuraWeightMap(auraWeightMap)
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