Skip to content

Commit

Permalink
Framework update
Browse files Browse the repository at this point in the history
  • Loading branch information
Tercioo committed Oct 12, 2023
1 parent ac21f31 commit da1e12c
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 68 deletions.
55 changes: 55 additions & 0 deletions Libs/DF/auras.lua
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,62 @@ local default_text_for_aura_frame = {
MANUAL_ADD_TRACKLIST_DEBUFF = "Add Debuff to Tracklist",
}

--store spell caches, they load empty and are filled when an addon require a cache with all spells
local spellsHashMap
local spellsIndexTable
local spellsWithSameName

local lazyLoadAllSpells = function(payload, iterationCount, maxIterations)
payload.nextIndex = payload.nextIndex or 0
local startPoint = payload.nextIndex
--the goal is iterate over 500000 spell ids over 200 frames
local endPoint = startPoint + 2500
payload.nextIndex = endPoint
local i = startPoint + 1

--make upvalues be closer
local toLowerCase = string.lower
local GetSpellInfo = GetSpellInfo
local hashMap = spellsHashMap
local indexTable = spellsIndexTable

while (i < endPoint) do
local spellName = GetSpellInfo(i)

if (spellName) then
spellName = toLowerCase(spellName)
hashMap[spellName] = i --[spellname] = spellId
indexTable[#indexTable+1] = spellName --array with all spellnames

local sameNameTable = spellsWithSameName[spellName]
if (not sameNameTable) then
sameNameTable = {}
spellsWithSameName[spellName] = sameNameTable
end
sameNameTable[#sameNameTable+1] = i
end

i = i + 1
end
end

function DF:LoadAllSpells(hashMap, indexTable, allSpellsSameName)
if (spellsHashMap) then
return spellsHashMap, spellsIndexTable, spellsWithSameName
end

assert(type(hashMap) == "table", "DetailsFramework:LoadAllSpells(): require a table on #1 parameter.")
assert(type(indexTable) == "table", "DetailsFramework:LoadAllSpells(): require a table on #2 parameter.")
assert(type(allSpellsSameName) == "table", "DetailsFramework:LoadAllSpells(): require a table on #3 parameter.")

spellsHashMap = hashMap
spellsIndexTable = indexTable
spellsWithSameName = allSpellsSameName

detailsFramework.Schedules.LazyExecute(lazyLoadAllSpells, {}, 200)

if 1 then return end

--pre checking which tables to fill to avoid checking if the table exists during the gigantic loop for performance
if (not DF.LoadingAuraAlertFrame) then
DF.LoadingAuraAlertFrame = CreateFrame("frame", "DetailsFrameworkLoadingAurasAlert", UIParent, "BackdropTemplate")
Expand Down
4 changes: 2 additions & 2 deletions Libs/DF/definitions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
---@field table df_table_functions
---@field IsValidSpecId fun(self:table, specId:number):boolean check if the passed specId is valid for the player class, also return false for tutorial specs
---@field DebugVisibility fun(self:table, object:uiobject) print the reason why the frame isn't shown in the screen
---@field Dispatch fun(self:table, callback:function, ...) : any dispatch a function call using xpcall
---@field Dispatch fun(self:table, callback:function, ...) : any dispatch a function call using xpcall, print to chat if the function passed is invalid
---@field QuickDispatch fun(self:table, callback:function, ...) : any dispatch a function call without errors if the function passed is invalid
---@field CoreDispatch fun(self:table, context:string, callback:function, ...) : any deprecated at this point, use Dispatch instead
---@field CoreDispatch fun(self:table, context:string, callback:function, ...) : any dispatch a function using xpcall, make an error if the function passed is invalid
---@field GetDefaultBackdropColor fun(self:table) : red, green, blue, alpha return the standard backdrop color used by blizzard on their own frames
---@field Msg fun(self:table, message:string, ...) show a message in the chat frame
---@field MsgWarning fun(self:table, message:string, ...) show a warning message in the chat frame
Expand Down
18 changes: 9 additions & 9 deletions Libs/DF/fw.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


local dversion = 474
local dversion = 475
local major, minor = "DetailsFramework-1.0", dversion
local DF, oldminor = LibStub:NewLibrary(major, minor)

Expand Down Expand Up @@ -4850,7 +4850,7 @@ local dispatch_error = function(context, errortext)
DF:Msg( (context or "<no context>") .. " |cFFFF9900error|r: " .. (errortext or "<no error given>"))
end

--safe call an external func with payload and without telling who is calling
--call a function with payload, if the callback doesn't exists, quit silently
function DF:QuickDispatch(func, ...)
if (type(func) ~= "function") then
return
Expand Down Expand Up @@ -5918,15 +5918,15 @@ function DF:DebugVisibility(UIObject)
print("Num Points:", numPoints > 0 and "|cFF00FF00" .. numPoints .. "|r" or "|cFFFF00000|r")
end

local beenchmarkTime = 0
local beenchmarkEnabled = false
local benchmarkTime = 0
local bBenchmarkEnabled = false
function _G.__benchmark(bNotPrintResult)
if (not beenchmarkEnabled) then
beenchmarkEnabled = true
beenchmarkTime = debugprofilestop()
if (not bBenchmarkEnabled) then
bBenchmarkEnabled = true
benchmarkTime = debugprofilestop()
else
local elapsed = debugprofilestop() - beenchmarkTime
beenchmarkEnabled = false
local elapsed = debugprofilestop() - benchmarkTime
bBenchmarkEnabled = false

if (bNotPrintResult) then
return elapsed
Expand Down
2 changes: 1 addition & 1 deletion Libs/DF/pictureedit.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ local CreateImageEditorFrame = function()
background_frame:SetSize(790, 560)
background_frame:SetClampedToScreen(true)

table.insert(UISpecialFrames, "DetailsFrameworkImageEditBackground")
tinsert(UISpecialFrames, "DetailsFrameworkImageEditBackground")

background_frame:SetResizable(true)
background_frame:SetMovable(true)
Expand Down
107 changes: 86 additions & 21 deletions Libs/DF/schedules.lua
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@

local DF = _G["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
local detailsFramework = _G["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end

local C_Timer = _G.C_Timer
local unpack = table.unpack or _G.unpack
local GetTime = GetTime

--make a namespace for schedules
DF.Schedules = DF.Schedules or {}
detailsFramework.Schedules = detailsFramework.Schedules or {}

DF.Schedules.AfterCombatSchedules = {
detailsFramework.Schedules.AfterCombatSchedules = {
withId = {},
withoutId = {},
}
Expand All @@ -24,21 +25,36 @@ DF.Schedules.AfterCombatSchedules = {
---@field SetName fun(object: timer, name: string)
---@field RunNextTick fun(callback: function)
---@field AfterCombat fun(callback:function, id:any, ...: any)
---@field CancelAfterCombat fun(id: any)
---@field CancelAllAfterCombat fun()
---@field IsAfterCombatScheduled fun(id: any): boolean
---@field LazyExecute fun(callback: function, payload: table?, maxIterations: number?, onEndCallback: function?): table

---@class df_looper : table
---@field payload table
---@field callback function
---@field loopEndCallback function?
---@field checkPointCallback function?
---@field nextCheckPoint number
---@field lastLoop number
---@field currentLoop number
---@field Cancel fun()
---@field IsCancelled fun(): boolean

local eventFrame = CreateFrame("frame")
eventFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
eventFrame:SetScript("OnEvent", function(self, event)
if (event == "PLAYER_REGEN_ENABLED") then
for _, schedule in ipairs(DF.Schedules.AfterCombatSchedules.withoutId) do
for _, schedule in ipairs(detailsFramework.Schedules.AfterCombatSchedules.withoutId) do
xpcall(schedule.callback, geterrorhandler(), unpack(schedule.payload))
end

for _, schedule in pairs(DF.Schedules.AfterCombatSchedules.withId) do
for _, schedule in pairs(detailsFramework.Schedules.AfterCombatSchedules.withId) do
xpcall(schedule.callback, geterrorhandler(), unpack(schedule.payload))
end

table.wipe(DF.Schedules.AfterCombatSchedules.withoutId)
table.wipe(DF.Schedules.AfterCombatSchedules.withId)
table.wipe(detailsFramework.Schedules.AfterCombatSchedules.withoutId)
table.wipe(detailsFramework.Schedules.AfterCombatSchedules.withId)
end
end)

Expand All @@ -52,7 +68,7 @@ local triggerScheduledLoop = function(tickerObject)

local result, errortext = pcall(callback, unpack(payload))
if (not result) then
DF:Msg("error on scheduler: ",tickerObject.path , tickerObject.name, errortext)
detailsFramework:Msg("error on scheduler: ",tickerObject.path , tickerObject.name, errortext)
end

local checkPointCallback = tickerObject.checkPointCallback
Expand Down Expand Up @@ -90,8 +106,10 @@ end
---@param loopEndCallback function?
---@param checkPointCallback function?
---@vararg any
function DF.Schedules.NewLooper(time, callback, loopAmount, loopEndCallback, checkPointCallback, ...)
---@return df_looper
function detailsFramework.Schedules.NewLooper(time, callback, loopAmount, loopEndCallback, checkPointCallback, ...)
local payload = {...}
---@type df_looper
local newLooper = C_Timer.NewTicker(time, triggerScheduledLoop, loopAmount)
newLooper.payload = payload
newLooper.callback = callback
Expand All @@ -110,13 +128,13 @@ local triggerScheduledTick = function(tickerObject)

local result, errortext = pcall(callback, unpack(payload))
if (not result) then
DF:Msg("error on scheduler: ",tickerObject.path , tickerObject.name, errortext)
detailsFramework:Msg("error on scheduler: ",tickerObject.path , tickerObject.name, errortext)
end
return result
end

--schedule to repeat a task with an interval of @time, keep ticking until cancelled
function DF.Schedules.NewTicker(time, callback, ...)
function detailsFramework.Schedules.NewTicker(time, callback, ...)
local payload = {...}
local newTicker = C_Timer.NewTicker(time, triggerScheduledTick)
newTicker.payload = payload
Expand All @@ -129,7 +147,7 @@ function DF.Schedules.NewTicker(time, callback, ...)
end

--schedule a task with an interval of @time
function DF.Schedules.NewTimer(time, callback, ...)
function detailsFramework.Schedules.NewTimer(time, callback, ...)
local payload = {...}
local newTimer = C_Timer.NewTimer(time, triggerScheduledTick)
newTimer.payload = payload
Expand All @@ -144,15 +162,15 @@ function DF.Schedules.NewTimer(time, callback, ...)
end

--cancel an ongoing ticker, the native call tickerObject:Cancel() also works with no problem
function DF.Schedules.Cancel(tickerObject)
function detailsFramework.Schedules.Cancel(tickerObject)
--ignore if there's no ticker object
if (tickerObject) then
return tickerObject:Cancel()
end
end

--schedule a task to be executed when the player leaves combat
function DF.Schedules.AfterCombat(callback, id, ...)
function detailsFramework.Schedules.AfterCombat(callback, id, ...)
local bInCombatLockdown = UnitAffectingCombat("player") or InCombatLockdown()

if (not bInCombatLockdown) then
Expand All @@ -163,28 +181,75 @@ function DF.Schedules.AfterCombat(callback, id, ...)
local payload = {...}

if (id) then
DF.Schedules.AfterCombatSchedules.withId[id] = {
detailsFramework.Schedules.AfterCombatSchedules.withId[id] = {
callback = callback,
payload = payload,
id = id,
}
else
table.insert(DF.Schedules.AfterCombatSchedules.withoutId, {
table.insert(detailsFramework.Schedules.AfterCombatSchedules.withoutId, {
callback = callback,
payload = payload,
})
end
end

function detailsFramework.Schedules.CancelAfterCombat(id)
detailsFramework.Schedules.AfterCombatSchedules.withId[id] = nil
end

function detailsFramework.Schedules.CancelAllAfterCombat()
table.wipe(detailsFramework.Schedules.AfterCombatSchedules.withId)
table.wipe(detailsFramework.Schedules.AfterCombatSchedules.withoutId)
end

function detailsFramework.Schedules.IsAfterCombatScheduled(id)
return detailsFramework.Schedules.AfterCombatSchedules.withId[id] ~= nil
end

---execute each frame a small portion of a big task
---the callback function receives a payload, the current iteration index and the max iterations
---if the callback function return true, the task is finished
---@param callback function
---@param payload table?
---@param maxIterations number?
---@param onEndCallback function?
function detailsFramework.Schedules.LazyExecute(callback, payload, maxIterations, onEndCallback)
assert(type(callback) == "function", "DetailsFramework.Schedules.LazyExecute() param #1 'callback' must be a function.")
maxIterations = maxIterations or 100000
payload = payload or {}
local iterationIndex = 1

local function wrapFunc()
local bIsFinished = callback(payload, iterationIndex, maxIterations)
if (not bIsFinished) then
iterationIndex = iterationIndex + 1
if (iterationIndex > maxIterations) then
detailsFramework:QuickDispatch(onEndCallback, payload)
return
end
C_Timer.After(0, function() wrapFunc() end)
else
detailsFramework:QuickDispatch(onEndCallback, payload)
return
end
end

wrapFunc()

return payload
end


--schedule a task with an interval of @time without payload
function DF.Schedules.After(time, callback)
function detailsFramework.Schedules.After(time, callback)
C_Timer.After(time, callback)
end

function DF.Schedules.SetName(object, name)
function detailsFramework.Schedules.SetName(object, name)
object.name = name
end

function DF.Schedules.RunNextTick(callback)
return DF.Schedules.After(0, callback)
function detailsFramework.Schedules.RunNextTick(callback)
return detailsFramework.Schedules.After(0, callback)
end
Loading

0 comments on commit da1e12c

Please sign in to comment.