annotate ObjectiveCore.lua @ 19:605e8f0e46db

ObjectiveCore / Style / Events / Frame - polishing the execution path for better performance - make use of the Blizzard_ObjectiveTracker bitfield values to ensure compatibility in possible secure hooks - avoid full updates when possible (using said bitfield values to indicate targeted sections) - extreme streamlining of event handling layout: specific reason updates are invoked from API hooks; broader updates are invoked by when the event listener catches something vague like 'QUEST_LOG_UPDATE'
author Nenue
date Wed, 06 Apr 2016 07:38:35 -0400
parents 880828018bf4
children 6bd2102d340b
rev   line source
Nenue@0 1 --- ${PACKAGE_NAME}
Nenue@0 2 -- @file-author@
Nenue@0 3 -- @project-revision@ @project-hash@
Nenue@0 4 -- @file-revision@ @file-hash@
Nenue@0 5 -- Created: 3/26/2016 1:51 AM
Nenue@19 6 local B, _G = select(2,...).frame, _G
Nenue@19 7 local pairs, setmetatable, type, tostring = _G.pairs, _G.setmetatable, _G.type, _G.tostring
Nenue@19 8 local format = _G.format
Nenue@16 9 local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
Nenue@0 10 local print = B.print('Objectives')
Nenue@19 11 local ObjectiveTrackerFrame, VeneerObjectiveScroll, CreateFrame = _G.ObjectiveTrackerFrame, _G.VeneerObjectiveScroll, _G.CreateFrame
Nenue@19 12 local Wrapper = _G.VeneerObjectiveWrapper
Nenue@19 13 local ipairs, tinsert, hooksecurefunc = _G.ipairs, _G.tinsert, _G.hooksecurefunc
Nenue@19 14 local Scroller = VeneerObjectiveWrapper.scrollArea
Nenue@19 15 local Scroll = _G.VeneerObjectiveScroll
Nenue@16 16
Nenue@16 17 --- Performance values
Nenue@16 18 --[[
Nenue@16 19 self:RegisterEvent("QUEST_LOG_UPDATE");
Nenue@16 20 self:RegisterEvent("TRACKED_ACHIEVEMENT_LIST_CHANGED");
Nenue@16 21 self:RegisterEvent("QUEST_WATCH_LIST_CHANGED");
Nenue@16 22 self:RegisterEvent("QUEST_AUTOCOMPLETE");
Nenue@16 23 self:RegisterEvent("QUEST_ACCEPTED");
Nenue@16 24 self:RegisterEvent("SUPER_TRACKED_QUEST_CHANGED");
Nenue@16 25 self:RegisterEvent("SCENARIO_UPDATE");
Nenue@16 26 self:RegisterEvent("SCENARIO_CRITERIA_UPDATE");
Nenue@16 27 self:RegisterEvent("TRACKED_ACHIEVEMENT_UPDATE");
Nenue@16 28 self:RegisterEvent("ZONE_CHANGED_NEW_AREA");
Nenue@16 29 self:RegisterEvent("ZONE_CHANGED");
Nenue@16 30 self:RegisterEvent("QUEST_POI_UPDATE");
Nenue@16 31 self:RegisterEvent("VARIABLES_LOADED");
Nenue@16 32 self:RegisterEvent("QUEST_TURNED_IN");
Nenue@16 33 self:RegisterEvent("PLAYER_MONEY");
Nenue@16 34 ]]
Nenue@16 35
Nenue@19 36
Nenue@19 37 --- These are the bitfields used by Blizzard_ObjectiveTracker to determine which segments get parsed.
Nenue@19 38 --- They are replicated here so that plugins can make use of any securehook args involving this info.
Nenue@19 39 local OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST -- 0x0100
Nenue@19 40 local OBJECTIVE_TRACKER_UPDATE_MODULE_AUTO_QUEST_POPUP = OBJECTIVE_TRACKER_UPDATE_MODULE_AUTO_QUEST_POPUP -- 0x0200
Nenue@19 41 local OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE = OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE -- 0x0400
Nenue@19 42 local OBJECTIVE_TRACKER_UPDATE_MODULE_SCENARIO = OBJECTIVE_TRACKER_UPDATE_MODULE_SCENARIO -- 0x0800
Nenue@19 43 local OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT = OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT -- 0x1000
Nenue@19 44
Nenue@19 45
Nenue@19 46 local OBJECTIVE_TRACKER_UPDATE_STATIC = OBJECTIVE_TRACKER_UPDATE_STATIC -- 0x0000
Nenue@19 47 local OBJECTIVE_TRACKER_UPDATE_ALL = OBJECTIVE_TRACKER_UPDATE_ALL -- 0xFFFF
Nenue@19 48 local OBJECTIVE_TRACKER_UPDATE_ID = OBJECTIVE_TRACKER_UPDATE_ID -- 0
Nenue@19 49
Nenue@19 50 local OBJECTIVE_TRACKER_UPDATE_QUEST = OBJECTIVE_TRACKER_UPDATE_QUEST -- 0x0001
Nenue@19 51 local OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED = OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED -- 0x0002
Nenue@19 52 local OBJECTIVE_TRACKER_UPDATE_TASK_ADDED = OBJECTIVE_TRACKER_UPDATE_TASK_ADDED -- 0x0004
Nenue@19 53 local OBJECTIVE_TRACKER_UPDATE_SCENARIO = OBJECTIVE_TRACKER_UPDATE_SCENARIO -- 0x0008
Nenue@19 54 local OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE = OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE -- 0x0010
Nenue@19 55 local OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT -- 0x0020
Nenue@19 56 local OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED -- 0x0040
Nenue@19 57 local OBJECTIVE_TRACKER_UPDATE_SCENARIO_BONUS_DELAYED = OBJECTIVE_TRACKER_UPDATE_SCENARIO_BONUS_DELAYED -- 0x0080
Nenue@19 58
Nenue@19 59 local OBJECTIVE_TRACKER_UPDATE_REASON = OBJECTIVE_TRACKER_UPDATE_ALL -- default
Nenue@19 60 --- Used to determine which trackers are listening for money events
Nenue@16 61 mod.MoneyReasons = 0
Nenue@0 62
Nenue@19 63 --- Baseline defaults table; values defined in the files that they pertain to
Nenue@16 64 mod.defaults = {}
Nenue@10 65
Nenue@19 66 --- Tracker display order
Nenue@16 67 mod.orderedNames = {'Bonus', 'AutoQuest', 'Quest', 'Cheevs'}
Nenue@0 68
Nenue@19 69 --- ipairs() argument tables
Nenue@19 70 mod.orderedHandlers = setmetatable({}, {__mode = "k"})
Nenue@19 71 mod.orderedTrackers = setmetatable({}, {__mode = "k"})
Nenue@19 72 mod.indexedTrackers = setmetatable({}, {__mode = "k"})
Nenue@0 73
Nenue@19 74 --- pairs() argument tables
Nenue@19 75 mod.namedTrackers = setmetatable({}, {__mode = "k"})
Nenue@19 76
Nenue@19 77 local WRAPPER_ANCHOR_POINT = 'TOPRIGHT'
Nenue@19 78 local WRAPPER_OFFSET_X = 0
Nenue@19 79 local WRAPPER_OFFSET_Y = -200
Nenue@19 80 local WRAPPER_MAX_HEIGHT = 670
Nenue@19 81 local WRAPPER_WIDTH = 280
Nenue@19 82 local WRAPPER_HEADER_HEIGHT = 24
Nenue@19 83
Nenue@19 84 mod.defaults.Wrapper = {
Nenue@19 85 AnchorPoint = WRAPPER_ANCHOR_POINT,
Nenue@19 86 OffsetX = WRAPPER_OFFSET_X,
Nenue@19 87 OffsetY = WRAPPER_OFFSET_Y,
Nenue@19 88 Height = WRAPPER_MAX_HEIGHT,
Nenue@19 89 Width = WRAPPER_WIDTH,
Nenue@19 90 HeaderHeight = WRAPPER_HEADER_HEIGHT
Nenue@19 91 }
Nenue@19 92 --- Tracker module definitions begin here; innards dealing with data retreival and output are defined further in
Nenue@19 93 mod.DefaultTracker = {
Nenue@19 94 previousHeight = 0,
Nenue@19 95
Nenue@19 96 name = "temp",
Nenue@19 97 displayName = "temp",
Nenue@19 98 updateReasonModule = 0xFF00,
Nenue@19 99 updateReasonEvent = 0x00FF,
Nenue@19 100
Nenue@19 101 numWatched = 0, --- number of entries being handled
Nenue@19 102 numBlocks = 0, --- number of blocks created
Nenue@19 103 actualBlocks = 0, --- number of blocks in use
Nenue@19 104
Nenue@19 105 freeBlocks = {}, --- block heap
Nenue@19 106 usedBlocks = {},
Nenue@19 107
Nenue@19 108 Info = {}, -- find data by ID
Nenue@19 109 BlockInfo = {}, -- find data by block ID
Nenue@19 110 Watched = {}, -- find watchIndex by data ID
Nenue@19 111 WatchInfo = {}, -- find data by watch index
Nenue@19 112 WatchBlock = {}, -- find block by watch index
Nenue@19 113 }
Nenue@19 114
Nenue@16 115 mod.AutoQuest = {
Nenue@14 116 name = "AutoQuest",
Nenue@16 117 displayName = "Notice",
Nenue@19 118 updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST,
Nenue@19 119 updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST +
Nenue@19 120 OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED,
Nenue@0 121 }
Nenue@16 122 mod.Quest = {
Nenue@14 123 name = "Quest",
Nenue@14 124 displayName = "Quests",
Nenue@19 125 updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST,
Nenue@19 126 updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST +
Nenue@19 127 OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED,
Nenue@0 128 }
Nenue@16 129 mod.Cheevs = {
Nenue@14 130 name = "Cheevs",
Nenue@14 131 displayName = "Achievements",
Nenue@19 132 updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT,
Nenue@19 133 updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT +
Nenue@19 134 OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED,
Nenue@14 135 }
Nenue@16 136 mod.Bonus = {
Nenue@14 137 name = "Bonus",
Nenue@14 138 displayName = "Bonus Objectives",
Nenue@19 139 updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE,
Nenue@19 140 updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST +
Nenue@19 141 OBJECTIVE_TRACKER_UPDATE_TASK_ADDED +
Nenue@19 142 OBJECTIVE_TRACKER_UPDATE_SCENARIO +
Nenue@19 143 OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE +
Nenue@19 144 OBJECTIVE_TRACKER_UPDATE_SCENARIO_BONUS_DELAYED
Nenue@0 145 }
Nenue@0 146
Nenue@19 147 local Tracker_string = function (self)
Nenue@19 148 return self.name
Nenue@19 149 end
Nenue@19 150 local Tracker_call = function (self, reason)
Nenue@19 151 self:Update(reason)
Nenue@19 152 end
Nenue@19 153
Nenue@19 154 local Tracker_Initialize = function (self, name, index)
Nenue@19 155 print('Initializing |cFF00FFFF'..name..'|r module...')
Nenue@16 156
Nenue@16 157 local handler = setmetatable(mod[name] or {}, {
Nenue@19 158 __tostring = Tracker_string,
Nenue@19 159 __call = Tracker_call
Nenue@0 160 })
Nenue@16 161 if type(mod.orderedHandlers[index]) == 'table' then
Nenue@16 162 return mod.orderedHandlers[index]
Nenue@0 163 end
Nenue@0 164
Nenue@19 165 print('|cFFFFFF00Acquiring locals')
Nenue@0 166 local preset = {}
Nenue@19 167 for k, _ in pairs(handler) do
Nenue@0 168 preset[k] = true
Nenue@0 169 end
Nenue@0 170
Nenue@16 171
Nenue@19 172 print('|cFFFF8800Inheriting')
Nenue@0 173 for k, v in pairs(self) do
Nenue@0 174 if not handler[k] then
Nenue@0 175 if type(v) == 'table' then
Nenue@0 176 -- assume all tables to be local data; don't inherit or ref
Nenue@0 177 handler[k] = {}
Nenue@0 178 else
Nenue@19 179 handler[k] = self[k]
Nenue@0 180 end
Nenue@19 181 print('copying', k)
Nenue@0 182 end
Nenue@0 183 end
Nenue@0 184 print('|cFFFF4400'..tostring(name)..'|r:')
Nenue@0 185 for k, v in pairs(handler) do
Nenue@19 186 print(format("%32s %8s %s", (preset[k] and '|cFFFFFFFF' or '|cFFFFFF00') .. k .. '|r', type(v), tostring(v)))
Nenue@0 187 end
Nenue@16 188
Nenue@16 189 mod[name] = handler
Nenue@16 190
Nenue@19 191 local trackerName = 'Veneer'..name..'Tracker'
Nenue@19 192 local handler = mod[name]
Nenue@19 193 local frame = CreateFrame('Frame', trackerName, _G.VeneerObjectiveScroll, 'VeneerTrackerTemplate')
Nenue@19 194 frame.title:SetText(handler.displayName)
Nenue@19 195 mod.SetBlockStyle(frame, 'Tracker', 'Normal')
Nenue@19 196 handler.frame = frame
Nenue@19 197 handler.trackerName = trackerName
Nenue@19 198 mod.orderedTrackers[index] = frame
Nenue@19 199 mod.namedTrackers[name] = frame
Nenue@19 200 mod.indexedTrackers[handler] = frame
Nenue@19 201 print('|cFFFF0088' .. trackerName .. '|r created for |cFF00FFFF' .. handler.displayName .. '|r module')
Nenue@19 202
Nenue@16 203 mod.orderedHandlers[index] = handler
Nenue@0 204 return true
Nenue@0 205 end
Nenue@0 206
Nenue@19 207 function mod:OnEvent (event, ...)
Nenue@19 208 local isHandled
Nenue@19 209 print('|cFF00FF00'.. event ..'|r', ...)
Nenue@19 210 if ( event == "QUEST_LOG_UPDATE" ) then
Nenue@19 211 mod:Update(OBJECTIVE_TRACKER_UPDATE_QUEST);
Nenue@19 212 elseif ( event == "TRACKED_ACHIEVEMENT_UPDATE" ) then
Nenue@19 213 --AchievementObjectiveTracker_OnAchievementUpdate(...);
Nenue@19 214 mod.Cheevs:Update(OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT)
Nenue@19 215 elseif ( event == "QUEST_ACCEPTED" ) then
Nenue@19 216 local questLogIndex, questID = ...;
Nenue@19 217 if ( IsQuestTask(questID) ) then
Nenue@19 218 mod:Update(OBJECTIVE_TRACKER_UPDATE_TASK_ADDED, questID);
Nenue@0 219 else
Nenue@19 220 if ( AUTO_QUEST_WATCH == "1" and GetNumQuestWatches() < MAX_WATCHABLE_QUESTS ) then
Nenue@19 221 AddQuestWatch(questLogIndex);
Nenue@19 222 SetSuperTrackedQuestID(questID);
Nenue@19 223 end
Nenue@19 224 end
Nenue@19 225 elseif ( event == "TRACKED_ACHIEVEMENT_LIST_CHANGED" ) then
Nenue@19 226 local achievementID, added = ...;
Nenue@19 227 if ( added ) then
Nenue@19 228 mod:Update(OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED, achievementID);
Nenue@19 229 else
Nenue@19 230 mod:Update(OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT);
Nenue@19 231 end
Nenue@19 232 elseif ( event == "QUEST_WATCH_LIST_CHANGED" ) then
Nenue@19 233 local questID, added = ...;
Nenue@19 234 if ( added ) then
Nenue@19 235 if ( not IsQuestTask(questID) ) then
Nenue@19 236 mod:Update(OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, questID);
Nenue@19 237 end
Nenue@19 238 else
Nenue@19 239 mod:Update(OBJECTIVE_TRACKER_UPDATE_QUEST);
Nenue@19 240 end
Nenue@19 241 elseif ( event == "QUEST_POI_UPDATE" ) then
Nenue@19 242 QuestPOIUpdateIcons();
Nenue@19 243 if ( GetCVar("trackQuestSorting") == "proximity" ) then
Nenue@19 244 SortQuestWatches();
Nenue@0 245 end
Nenue@0 246
Nenue@19 247 mod:Update(OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST);
Nenue@19 248
Nenue@19 249 elseif ( event == "SCENARIO_CRITERIA_UPDATE" ) then
Nenue@19 250 mod:Update(OBJECTIVE_TRACKER_UPDATE_SCENARIO);
Nenue@19 251 elseif ( event == "SUPER_TRACKED_QUEST_CHANGED" ) then
Nenue@19 252 mod:Update(OBJECTIVE_TRACKER_UPDATE_QUEST)
Nenue@19 253 elseif ( event == "ZONE_CHANGED" ) then
Nenue@19 254 local inMicroDungeon = IsPlayerInMicroDungeon();
Nenue@19 255 if ( inMicroDungeon ~= self.inMicroDungeon ) then
Nenue@19 256 if ( not WorldMapFrame:IsShown() and GetCVarBool("questPOI") ) then
Nenue@19 257 SetMapToCurrentZone(); -- update the zone to get the right POI numbers for the tracker
Nenue@19 258 end
Nenue@19 259 --SortQuestWatches();
Nenue@19 260 self.inMicroDungeon = inMicroDungeon;
Nenue@19 261 end
Nenue@19 262 elseif ( event == "QUEST_AUTOCOMPLETE" ) then
Nenue@19 263 local questId = ...;
Nenue@19 264 AddAutoQuestPopUp(questId, "COMPLETE");
Nenue@19 265 elseif ( event == "SCENARIO_UPDATE" ) then
Nenue@19 266 local newStage = ...;
Nenue@19 267 if ( newStage ) then
Nenue@19 268 mod:Update(OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE);
Nenue@19 269 else
Nenue@19 270 mod:Update(OBJECTIVE_TRACKER_UPDATE_SCENARIO);
Nenue@19 271 end
Nenue@19 272 elseif ( event == "ZONE_CHANGED_NEW_AREA" ) then
Nenue@19 273 if ( not WorldMapFrame:IsShown() and GetCVarBool("questPOI") ) then
Nenue@19 274 SetMapToCurrentZone(); -- update the zone to get the right POI numbers for the tracker
Nenue@19 275 end
Nenue@19 276 SortQuestWatches();
Nenue@19 277 elseif ( event == "QUEST_TURNED_IN" ) then
Nenue@19 278 local questID, xp, money = ...;
Nenue@19 279 if ( IsQuestTask(questID) ) then
Nenue@19 280 mod.Bonus:Update()
Nenue@19 281 end
Nenue@19 282 elseif ( event == "PLAYER_MONEY" and self.watchMoneyReasons > 0 ) then
Nenue@19 283 mod:Update(self.watchMoneyReasons);
Nenue@0 284 end
Nenue@0 285 end
Nenue@0 286
Nenue@19 287 --- Done once per ui load
Nenue@19 288 local BlizzHooks = {
Nenue@19 289 ['AddQuestWatch'] = 'AddQuestWatch',
Nenue@19 290 ['RemoveQuestWatch'] = 'RemoveQuestWatch',
Nenue@19 291 ['AbandonQuest'] = 'AbandonQuest',
Nenue@19 292 ['AcknowledgeAutoAcceptQuest'] = 'AcknowledgeAutoAcceptQuest',
Nenue@19 293 ['AddAutoQuestPopUp'] = 'AddAutoQuestPopUp',
Nenue@19 294 ['RemoveAutoQuestPopUp'] = 'RemoveAutoQuestPopUp',
Nenue@19 295 ['AddTrackedAchievement'] = 'AddTrackedAchievement',
Nenue@19 296 ['RemoveTrackedAchievement'] = 'RemoveTrackedAchievement',
Nenue@19 297 ['SetSuperTrackedQuestID'] = 'SetSuperTrackedQuestID'
Nenue@19 298 }
Nenue@19 299 local VeneerData
Nenue@16 300 function mod:OnInitialize()
Nenue@19 301 local c = mod.Conf.Wrapper
Nenue@19 302 VeneerData = _G.VeneerData
Nenue@19 303 VeneerData.CallLog = VeneerData.CallLog or {}
Nenue@19 304 if not mod.isHooked then
Nenue@19 305 mod.isHooked = true
Nenue@19 306 for blizzFunc, veneerFunc in pairs(BlizzHooks) do
Nenue@19 307 if mod[veneerFunc] then
Nenue@19 308 hooksecurefunc(blizzFunc, mod[veneerFunc])
Nenue@19 309 else
Nenue@19 310 hooksecurefunc(blizzFunc, function(...)
Nenue@19 311 print('|cFFFF0088securehook('..tostring(blizzFunc)..')|r args:', ...)
Nenue@19 312 tinsert(VeneerData.CallLog, {blizzFunc, ...})
Nenue@19 313 end)
Nenue@19 314 end
Nenue@19 315 end
Nenue@19 316 end
Nenue@19 317 Scroller:SetScrollChild(Scroll)
Nenue@19 318 Scroller:SetWidth(c.Width)
Nenue@19 319 Scroll:SetPoint('TOPLEFT', Scroller, 'TOPLEFT')
Nenue@19 320 Scroll:SetWidth(c.Width)
Nenue@0 321 ObjectiveTrackerFrame:UnregisterAllEvents()
Nenue@0 322 ObjectiveTrackerFrame:Hide()
Nenue@0 323 end
Nenue@19 324
Nenue@19 325 --- Done any time the the minimize button is toggled up
Nenue@19 326
Nenue@19 327 function mod:OnEnable()
Nenue@19 328 for id, name in ipairs(mod.orderedNames) do
Nenue@19 329 if not mod.orderedHandlers[id] then
Nenue@19 330 Tracker_Initialize(mod.DefaultTracker, name, id)
Nenue@19 331 end
Nenue@19 332 end
Nenue@19 333
Nenue@19 334 for event, func in pairs(mod) do
Nenue@19 335 if type(func) == 'function' and event:match('^[A-Z_]+$') then
Nenue@19 336 print('|cFFFF44FFlistening to', event)
Nenue@19 337 Wrapper:RegisterEvent(event)
Nenue@19 338 end
Nenue@19 339 end
Nenue@19 340
Nenue@19 341 local c = mod.Conf.Wrapper
Nenue@19 342 Wrapper:SetPoint(c.AnchorPoint, UIParent, c.AnchorPoint, c.OffsetX, c.OffsetY)
Nenue@19 343 B.Conf.FramePosition[Wrapper:GetName()] = {c.AnchorPoint, c.AnchorPoint, c.OffsetX, c.OffsetY}
Nenue@19 344 Wrapper:SetWidth(c.Width)
Nenue@19 345
Nenue@19 346
Nenue@19 347 mod.InitializeWidgets()
Nenue@19 348 mod:Update()
Nenue@19 349 end
Nenue@19 350
Nenue@19 351 function mod:OnDisable()
Nenue@19 352
Nenue@19 353 end
Nenue@19 354
Nenue@19 355