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.

/src/ChorusCastFrameTemplate.lua (37fbfc609f76638e21020ac55914740db198ec34) (6796 bytes) (mode 100644) (type blob)

local Chorus = Chorus

local GetTime = GetTime
local UnitCastingInfo = Chorus.test.UnitCastingInfo or UnitCastingInfo
local UnitChannelInfo = Chorus.test.UnitChannelInfo or UnitChannelInfo
local UnitExists = Chorus.test.UnitExists or UnitExists
local UnitIsUnit = Chorus.test.UnitIsUnit or UnitIsUnit

local SecureButton_GetUnit = Chorus.test.SecureButton_GetUnit or SecureButton_GetUnit

local function getDurationRemainingSec(nowMili, startInstanceMili, endInstanceMili)
	assert(nowMili ~= nil)
	assert('number' == type(nowMili))

	assert(startInstanceMili ~= nil)
	assert('number' == type(startInstanceMili))

	assert(endInstanceMili ~= nil)
	assert('number' == type(endInstanceMili))

	local durationRemainingSec = (endInstanceMili - nowMili) / 1000

	assert(durationRemainingSec ~= nil)
	assert('number' == type(durationRemainingSec))
	assert(durationRemainingSec >= 0 or durationRemainingSec <= 0)

	return durationRemainingSec
end

local function getCastInfo(unitDesignation)
	assert(unitDesignation ~= nil)

	local spellName = UnitCastingInfo(unitDesignation)
	if spellName then
		return UnitCastingInfo(unitDesignation)
	else
		return UnitChannelInfo(unitDesignation)
	end
end

local function castFrameEventIsRelevant(self, eventCategory, ...)
	assert(self ~= nil)
	assert(eventCategory ~= nil)

	local u = SecureButton_GetUnit(self)
	local eu = select(1, ...)
	if eu and u then
		return UnitIsUnit(u, eu)
	else
		return true
	end
end

local function applyArtworkSpellIcon(self, pictureFile)
	assert(self ~= nil)

	if not pictureFile then
		pictureFile = 'Interface\\Icons\\INV_Misc_QuestionMark'
	end

	assert(pictureFile ~= nil)
	assert('string' == type(pictureFile))
	pictureFile = strtrim(pictureFile)
	assert(string.len(pictureFile) >= 1)
	assert(string.len(pictureFile) <= 8192)

	--[[ Artwork1: spell icon ]]--
	local artwork1 = self.artwork1 or _G[self:GetName() .. 'Artwork1']
	assert(artwork1 ~= nil)

	artwork1:SetTexture(pictureFile)
end

local function applySpellName(self, spellName)
	assert(self ~= nil)

	if not spellName then
		spellName = 'Unknown'
	end

	assert(spellName ~= nil)
	assert('string' == type(spellName))
	spellName = strtrim(spellName)
	assert(string.len(spellName) >= 1)
	assert(string.len(spellName) <= 8192)

	local label1 = self.label1 or _G[self:GetName() .. 'Text1']
	assert(label1 ~= nil)

	label1:SetText(spellName)
end

local function applyArtworkCastBar(self, unitDesignation, shieldedFlag)
	assert(self ~= nil)

	assert(unitDesignation ~= nil)
	assert('string' == type(unitDesignation))
	unitDesignation = string.lower(strtrim(unitDesignation))
	assert(string.len(unitDesignation) >= 1)
	assert(string.len(unitDesignation) <= 256)

	local label1 = self.label1 or _G[self:GetName() .. 'Text1']
	assert(label1 ~= nil)

	--[[ Artwork2: bar texture ]]--
	local artwork2 = self.artwork2 or _G[self:GetName() .. 'Artwork2']
	assert(artwork2 ~= nil)

	if shieldedFlag then
		artwork2:SetVertexColor(248 / 255, 248 / 255, 1)
		label1:SetTextColor(1, 215 / 255, 0)
	elseif UnitIsFriend('player', unitDesignation) then
		artwork2:SetVertexColor(143 / 255, 188 / 255, 143 / 255)
		label1:SetTextColor(248 / 255, 248 / 255, 1)
	else
		artwork2:SetVertexColor(1, 69 / 255, 0)
		label1:SetTextColor(248 / 255, 248 / 255, 1)
	end
end

local function applyDurationRemainingSec(self, durationRemainingSec)
	assert(self ~= nil)

	assert(durationRemainingSec ~= nil)
	assert('number' == type(durationRemainingSec))

	local label2 = self.label2 or _G[self:GetName() .. 'Text2']
	assert(label2 ~= nil)

	local t = string.format('%.1f', durationRemainingSec)
	label2:SetText(t)
end

local function applyBounds(self, startInstance, endInstance)
	assert(self ~= nil)

	assert(startInstance ~= nil)
	assert('number' == type(startInstance))
	startInstance = math.abs(startInstance)
	assert(startInstance >= 0)

	assert(endInstance ~= nil)
	assert('number' == type(endInstance))
	endInstance = math.abs(endInstance)
	assert(endInstance >= 0)

	local x = math.min(startInstance, endInstance)
	local y = math.max(startInstance, endInstance)
	assert(x <= y)

	self:SetMinMaxValues(x, y)
end

local function applyCurrentInstanceMili(self, nowMili)
	assert(self ~= nil)

	assert(nowMili ~= nil)
	assert('number' == type(nowMili))
	nowMili = math.abs(nowMili)
	assert(nowMili >= 0)

	self:SetValue(nowMili)
end

local function castFrameEventProcessor(self, eventCategory, ...)
	assert(self ~= nil)

	if not castFrameEventIsRelevant(self, eventCategory, ...) then
		return
	end

	local u = SecureButton_GetUnit(self)
	if not u or not UnitExists(u) then
		self:Hide()
		return
	end

	local label2 = self.label2 or _G[self:GetName() .. 'Text2']
	assert(label2 ~= nil)

	local spellName, _, _, pictureFile, startInstance, endInstance, _, _, shieldedFlag = getCastInfo(u)

	local castOngoingFlag = spellName ~= nil
	if castOngoingFlag then
		applyBounds(self, startInstance, endInstance)

		local now = GetTime() * 1000
		applyCurrentInstanceMili(self, now)

		local dur = getDurationRemainingSec(now, startInstance, endInstance)
		applyDurationRemainingSec(self, dur)

		applyArtworkSpellIcon(self, pictureFile)
		applyArtworkCastBar(self, u, shieldedFlag)
		applySpellName(self, spellName)
		self:Show()
	else
		self:Hide()
	end
end

local function castFrameUpdateProcessor(self)
	assert(self ~= nil)

	local u = SecureButton_GetUnit(self)
	if not u then
		return
	end

	local now = GetTime() * 1000
	applyCurrentInstanceMili(self, now)

	local a, b = self:GetMinMaxValues()
	local durationRemainingSec = getDurationRemainingSec(now, a, b)

	applyDurationRemainingSec(self, durationRemainingSec)
end

local function castFrameMain(self)
	assert(self ~= nil)

	local n = self:GetName()
	assert(n ~= nil)

	self.artwork1 = _G[n .. 'Artwork1']
	assert(self.artwork1 ~= nil)

	self.artwork2 = _G[n .. 'Artwork2']
	assert(self.artwork2 ~= nil)

	self.label1 = _G[n .. 'Text1']
	assert(self.label1 ~= nil)

	self.label2 = _G[n .. 'Text2']
	assert(self.label2 ~= nil)

	self:SetScript('OnEvent', castFrameEventProcessor)
	self:SetScript('OnUpdate', castFrameUpdateProcessor)

	self:RegisterEvent("PLAYER_ENTERING_WORLD");
	self:RegisterEvent("PLAYER_FOCUS_CHANGED");
	self:RegisterEvent("PLAYER_TARGET_CHANGED");
	self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START");
	self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP");
	self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE");
	self:RegisterEvent("UNIT_SPELLCAST_DELAYED");
	self:RegisterEvent("UNIT_SPELLCAST_FAILED");
	self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED");
	self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTIBLE");
	self:RegisterEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE");
	self:RegisterEvent("UNIT_SPELLCAST_START");
	self:RegisterEvent("UNIT_SPELLCAST_STOP");
end

Chorus.castFrameMain = function(...)
	return castFrameMain(...)
end


Mode Type Size Ref File
100644 blob 35 5c40e6e2862d70b5c51c326a13073a4012ac05c7 .gitignore
100644 blob 1095 ea691376a4847fd792cb2ae4b1ffebbd6bd6e22a Makefile
100644 blob 3394 190d35463349336b8ed9d90078342c5643600a29 README.adoc
100644 blob 234 fca3e2be1b6aacf0e93e898255a4049a33b35d36 chorus.toc
040000 tree - cac8af7ca5d8adc7771598e6faae482998b25fa2 doc
040000 tree - b232717e4ce1bb949a6e4e68fbf679b026b48fd0 etc
040000 tree - c04e1001c2dd401037b01ddd04fdeccc99be2ec3 share
040000 tree - ebdeb4d98909af86d2423f9845ed706466beccbc src
040000 tree - aa42c74ca307c2c3c635efd4186be6e5404a6303 test
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