comparison ClassPlan.lua @ 40:589c444d4837

WowAce/Curseforge migration push
author Nenue
date Sun, 25 Dec 2016 13:04:57 -0500
parents 26dfa661daa7
children 79e5e96e5f18
comparison
equal deleted inserted replaced
39:89ddef0594bc 40:589c444d4837
1 local _, db = ...
1 local wipe, tinsert, sort = table.wipe, tinsert, table.sort 2 local wipe, tinsert, sort = table.wipe, tinsert, table.sort
2 local pairs, ipairs = pairs, ipairs 3 local pairs, ipairs = pairs, ipairs
3 local floor, mod, time = floor, mod, time 4 local floor, mod, time = floor, mod, time
4 local max, min = math.max, math.min 5 local max, min = math.max, math.min
5 local GetTime = GetTime 6 local GetTime = GetTime
6 local GI_currentTime = time() 7 local GI_currentTime = time()
7 local print = DEVIAN_WORKSPACE and function(...) print('ClassPlan', ...) end or nop 8 local print = DEVIAN_WORKSPACE and function(...) print('ClassPlan', ...) end or nop
8 9
9 local CG_GetBuildings = C_Garrison.GetBuildings
10 local CG_GetFollowerShipments = C_Garrison.GetFollowerShipments
11 local CG_GetLooseShipments = C_Garrison.GetLooseShipments
12 local CG_GetTalentTrees = C_Garrison.GetTalentTrees
13 local CG_GetCompleteTalent = C_Garrison.GetCompleteTalent
14 local CG_GetLandingPageShipmentInfo = C_Garrison.GetLandingPageShipmentInfo
15 local CG_GetLandingPageShipmentInfoByContainerID = C_Garrison.GetLandingPageShipmentInfoByContainerID
16
17 local CP_REPLACE_LANDINGPAGE = true 10 local CP_REPLACE_LANDINGPAGE = true
18 local CP_HEADER_SIZE = 24 11 local CP_HEADER_SIZE = 24
19 local CP_BACKGROUND_COLOR = { 12 db.ClassPlanDefaultType = {
20 inProgress = {0, 0, 0, 0.5}, 13
21 shipmentsReady = {0, 0, 0, 0.25}, 14 backgroundColor = {0, 0, 0, 0.5},
22 complete = {0.5, 0.5, 0.5, 0.5} 15 textColor = {1,1,1,1}
16 }
17 db.ClassPlanTypes = setmetatable({}, {__index = db.ClassPlanDefaultType})
18 db.ClassPlanTypes.inProgress = {
19 backgroundColor = {0, 0, 0, 0.5},
20 textColor = {1,1,1}
21 }
22 db.ClassPlanTypes.shipmentsReady = {
23 backgroundColor = {1, 1, 0, 0.25 },
24 textColor = {1, 1, 0}
25 }
26 db.ClassPlanTypes.complete = {
27 backgroundColor = {0, 1, 0, 0.25 },
28 textColor = {0, 1, 0}
23 } 29 }
24 30
25 local GetTimeLeftString = function(timeLeft) 31 local GetTimeLeftString = function(timeLeft)
26 local days = floor(timeLeft/(24*3600)) 32 local days = floor(timeLeft/(24*3600))
27 local hours = floor(mod(timeLeft, (24*3600)) / 3600) 33 local hours = floor(mod(timeLeft, (24*3600)) / 3600)
31 return (days .. 'd' .. ' ') .. ((hours > 0) and (hours .. 'h') or '') 37 return (days .. 'd' .. ' ') .. ((hours > 0) and (hours .. 'h') or '')
32 else 38 else
33 return ((hours > 0) and (hours .. 'h') or '') .. ((minutes > 0) and (' ' ..minutes .. ' min') or '') 39 return ((hours > 0) and (hours .. 'h') or '') .. ((minutes > 0) and (' ' ..minutes .. ' min') or '')
34 end 40 end
35 end 41 end
36
37 42
38 ClassOrderPlanCore = { 43 ClassOrderPlanCore = {
39 events = {}, 44 events = {},
40 freeBlocks = {}, 45 freeBlocks = {},
41 characterButtons = {}, 46 characterButtons = {},
43 sortedItems = {}, 48 sortedItems = {},
44 timers = {}, 49 timers = {},
45 shipments = {}, 50 shipments = {},
46 playerFirst = false, 51 playerFirst = false,
47 prototypes = {}, 52 prototypes = {},
48 Queued = {} 53 Queued = {},
54 Timers = {},
55 ReportChunks = {},
49 } 56 }
50 local MissionList = { 57 ClassPlanHandlerBase = {
51 templateName = 'ClassPlanMissionEntry',
52 listKey = {'missions', 'available'},
53 listTitle = {'In Progress', 'Available'},
54
55 point = 'TOPLEFT',
56 relativePoint ='TOPLEFT',
57 events = {
58 'GARRISON_MISSION_LIST_UPDATE',
59 'GARRISON_LANDINGPAGE_SHIPMENTS'},
60 }
61 local ShipmentList = {
62 templateName = 'ClassPlanShipmentEntry',
63 listKey = {'shipments'},
64 listTitle = {'Work Orders'},
65 events = {
66 'GARRISON_MISSION_LIST_UPDATE',
67 'GARRISON_LANDINGPAGE_SHIPMENTS',
68 'GARRISON_TALENT_UPDATE',
69 "GARRISON_TALENT_COMPLETE",
70 "GARRISON_SHIPMENT_RECEIVED",
71 'GARRISON_FOLLOWER_LIST_UPDATE',
72 'GARRISON_SHOW_LANDING_PAGE'},
73 }
74 local SharedHandlers = {
75 numBlocks = 0, 58 numBlocks = 0,
76 isStale = true, 59 isStale = true,
77 maxItems = 10 60 maxItems = 10
78 } 61 }
79 local SharedEntry = {} 62 ClassPlanEntryBase = {}
80 local ShipmentEntry = {}
81 local MissionEntry = {}
82 63
83 local ClassPlan = ClassOrderPlanCore 64 local ClassPlan = ClassOrderPlanCore
65 local Embed = function(object, ...)
66 for i = 1, select('#', ...) do
67 local src = select(i, ...)
68 for k,v in pairs(src) do
69 if not object[k] then
70 object[k] = v
71 end
72 end
73 end
74 return object
75 end
84 76
85 function ClassPlan:OnLoad () 77 function ClassPlan:OnLoad ()
86 self:RegisterEvent('PLAYER_LOGIN') 78 self:RegisterEvent('PLAYER_LOGIN')
87 self:RegisterEvent('ADDON_LOADED') 79 self:RegisterEvent('ADDON_LOADED')
88 self:RegisterEvent('PLAYER_REGEN_ENABLED') 80 self:RegisterEvent('PLAYER_REGEN_ENABLED')
89 self:RegisterEvent('PLAYER_REGEN_DISABLED') 81 self:RegisterEvent('PLAYER_REGEN_DISABLED')
82 self:RegisterEvent('GARRISON_SHOW_LANDING_PAGE')
90 self:RegisterForDrag('LeftButton') 83 self:RegisterForDrag('LeftButton')
91 self:SetMovable(true) 84 self:SetMovable(true)
92 self:SetToplevel(true) 85 self:SetToplevel(true)
93
94 86
95 SLASH_CLASSPLAN1 = "/classplan" 87 SLASH_CLASSPLAN1 = "/classplan"
96 SLASH_CLASSPLAN2 = "/cp" 88 SLASH_CLASSPLAN2 = "/cp"
97 SlashCmdList.CLASSPLAN = function(args) 89 SlashCmdList.CLASSPLAN = function(args)
98 self:Toggle() 90 self:Toggle()
99 end 91 end
100 92
101 end 93 local originalScript = GarrisonLandingPageMinimapButton:GetScript('OnClick')
94 GarrisonLandingPageMinimapButton:SetScript("OnClick", function(minimap, button)
95 if button == 'LeftButton' and (not IsShiftKeyDown()) then
96 self:Toggle()
97 else
98 originalScript(minimap, button)
99 end
100 end)
101 self.FadeOut:SetScript('OnFinished', function()
102 self:Hide()
103 self.data.IsShown = nil
104 self.isAnimating = nil
105 end)
106 self.FadeIn:SetScript('OnPlay', function()
107 self.isAnimating = true
108 self:SetShown(true)
109 end)
110
111 --hooksecurefunc(C_Garrison, 'RequestLandingPageShipmentInfo', function()
112 -- WorldPlan:print("Requesting shipments data.")
113 --end)
114 C_Garrison.RequestLandingPageShipmentInfo();
115 self.isStale = true
116 end
117
102 118
103 function ClassPlan:GetCurrentProfile() 119 function ClassPlan:GetCurrentProfile()
104 WorldPlanData.OrderHall = WorldPlanData.OrderHall or {} 120 WorldPlanData.OrderHall = WorldPlanData.OrderHall or {}
105 local db = WorldPlanData.OrderHall 121 local db = WorldPlanData.OrderHall
106 self.data = db 122 self.data = db
108 local characters = db.characters or {} 124 local characters = db.characters or {}
109 db.characters = characters 125 db.characters = characters
110 126
111 local name, realm = UnitName('player') 127 local name, realm = UnitName('player')
112 realm = realm or GetRealmName() 128 realm = realm or GetRealmName()
129
113 local profileName = name .. '-' .. realm 130 local profileName = name .. '-' .. realm
114 131 self.profile = characters[profileName] or {
115 self.profile = characters[profileName] or {} 132 showItems = true
133 }
116 self.characters = characters 134 self.characters = characters
117 characters[profileName] = self.profile 135 characters[profileName] = self.profile
118 136
119
120 local classColor = RAID_CLASS_COLORS[select(2, UnitClass('player'))] 137 local classColor = RAID_CLASS_COLORS[select(2, UnitClass('player'))]
121 local className = UnitClass('player') 138 local className = UnitClass('player')
122
123 print('|cFFFFFF00Loaded:|r', classColor.hex, className, profileName) 139 print('|cFFFFFF00Loaded:|r', classColor.hex, className, profileName)
124 self.Background:SetColorTexture(classColor.r, classColor.g, classColor.b, 0.5)
125 self.profile.classColor = classColor 140 self.profile.classColor = classColor
126 self.profile.className = className 141 self.profile.className = className
127 self.profile.characterName = name 142 self.profile.characterName = name
128 self.profile.characterRealm = realm 143 self.profile.characterRealm = realm
144 -- flip it on
145 self.profile.showItems = true
146
147 self.HeaderInset:SetHeight(CP_HEADER_SIZE)
148 self.ClassStripe:SetColorTexture(classColor.r, classColor.g, classColor.b, 1)
149 self.ClassStripe:SetPoint('TOPLEFT', self.HeaderInset, 'BOTTOMLEFT')
150
129 return self.profile 151 return self.profile
130 end 152 end
131 153
132 function ClassPlan:SetupHandler(handler) 154 function ClassPlan:AddHandler(frame)
133 print('|cFF00FF00'..handler:GetName()..' loaded') 155 print('|cFF00FF00'..frame:GetName()..' loaded')
134 for i, event in ipairs(handler.events) do 156 for i, event in ipairs(frame.events) do
135 print('|cFF00FF00 event', event) 157 print('|cFF00FF00 event', event)
136 handler:RegisterEvent(event) 158 frame:RegisterEvent(event)
137 end 159 end
138 for index, listKey in ipairs(handler.listKey) do 160 frame.sortedItems = {}
161 for index, listKey in ipairs(frame.listKey) do
162 frame.profile = self.profile
163 frame.data = self.data
139 self.profile[listKey] = self.profile[listKey] or {} 164 self.profile[listKey] = self.profile[listKey] or {}
140 local listTitle = handler.listTitle[index] 165 local listTitle = frame.listTitle[index]
141 setmetatable(self.profile[listKey], { __tostring = listTitle }) 166 setmetatable(self.profile[listKey], { __tostring = function() return listTitle end })
142 end 167 frame.sortedItems[listKey] = {}
143 handler:SetList(1) 168
144 handler.sortedItems = {} 169 end
170 frame.owningFrame = self
171 frame:SetList(1)
145 end 172 end
146 173
147 function ClassPlan:OnEvent (event, arg) 174 function ClassPlan:OnEvent (event, arg)
148 print(event, arg) 175 print(event, arg)
149 if event == 'PLAYER_REGEN_DISABLED' then 176 if event == 'PLAYER_REGEN_DISABLED' then
163 end 190 end
164 elseif event == 'PLAYER_LOGIN' then 191 elseif event == 'PLAYER_LOGIN' then
165 if not self.initialized then 192 if not self.initialized then
166 self:Setup() 193 self:Setup()
167 end 194 end
195 elseif event == 'GARRISON_SHOW_LANDING_PAGE' then
196 self:RefreshData()
168 end 197 end
169 end 198 end
170 199
171 function ClassPlan:Setup() 200 function ClassPlan:Setup()
172 if IsLoggedIn() then 201 if IsLoggedIn() then
173 print('|cFFFFFF00'..self:GetName()..':Setup()|r') 202 print('|cFFFFFF00'..self:GetName()..':Setup()|r')
174 203
175 self:GetCurrentProfile() 204 self:GetCurrentProfile()
176 for _, handler in ipairs(self.Handlers) do 205 for _, handler in ipairs(self.Handlers) do
177 self:SetupHandler(handler) 206 self:AddHandler(handler)
207 handler.initialized = true
178 end 208 end
179 self.initialized = true 209 self.initialized = true
180 self:SetShown(self.data.IsShown) 210 self:SetShown(self.data.IsShown)
211
212
181 end 213 end
182 end 214 end
183 215
184 216
185 --- Update space 217 --- Update space
186 218
187 local max = math.max 219 local max = math.max
188 function ClassPlan:Update() 220 function ClassPlan:RefreshData()
189 print('|cFF00FFFFRefresh()|r') 221 local detailsFailed
190 self.currentHeight = 0 222 for index, handler in pairs(self.Handlers) do
191 for index, handler in pairs(self.Handlers) do 223 print(' |cFF00FF00'..handler:GetName()..' data update|r')
192 if handler.isStale then 224 handler:RefreshData()
193 print(' |cFF00FF00'..index..' '..handler:GetName()..'|r') 225 end
194 local sortedItems = handler.sortedItems 226 if detailsFailed then
195 local activeKey = handler.activeKey 227 db.print('Unable to obtain player details. Trying again later.')
196 228 else
197 handler.profile = self.profile[handler.activeKey] 229 self.requestingData = nil
198 handler.currentTime = GI_currentTime 230 end
199 handler:GetPlayerData(self.profile) 231 end
200 wipe(sortedItems) 232
201 for key, profile in pairs(self.data.characters) do 233 function ClassPlan:Update()
202 print('profile', key, activeKey) 234 print('|cFF00FFFF'..self:GetName()..'Refresh()|r')
203 local profileList = profile[activeKey] 235
204 if profileList and #profileList >= 1 then 236 self.currentHeight = 0
205 local classColor = profile.classColor or RAID_CLASS_COLORS['HUNTER'] 237 for index, handler in ipairs(self.Handlers) do
206 local isMine = (profile == self.profile) 238 local itemsHeight = handler:UpdateItems()
207 for index, data in ipairs(profileList) do 239 if itemsHeight then
208 data.classColor = classColor 240 self.currentHeight = max(itemsHeight, self.currentHeight)
209 data.profileKey = key 241 end
210 data.isMine = isMine 242 end
211 if handler.OnGetItem then 243
212 handler:OnGetItem(data) 244 local index = 1
213 end 245 for key, info in pairs(self.data.characters) do
214 tinsert(sortedItems, data) 246 print('cbutton', key)
215 end 247 if self.data[key] then
216 end 248 print('|cFFFF4400remove legacy value', key)
217 end 249 self.data[key] = nil
218 250 end
219 if handler.SortHandler then 251
220 sort(sortedItems, handler.SortHandler) 252
221 end 253 local button = self.characterButtons[index]
222 254 if not button then
255 button = CreateFrame('Button', nil, self, 'ClassOrderPlanCharacterButton')
256 button:SetID(index)
257 self.characterButtons[index] = button
258
259 if not self.lastButton then
260 button:SetPoint('TOPLEFT', self.HeaderInset, 'TOPLEFT', 0, 0)
261 else
262 button:SetPoint('TOPLEFT', self.lastButton, 'TOPRIGHT', 2, 0)
223 end 263 end
224 handler.isStale = nil 264 self.lastButton = button
225 local itemsHeight = handler:UpdateItems() 265 end
226 self.currentHeight = max(itemsHeight, self.currentHeight) 266 if not info.characterName then
227 267 info.characterName, info.characterRealm = key:match("%(.+)%-(.+)^")
228 end 268 end
229 269
230 local index = 1 270 print(info.characterName)
231 for id, profile in pairs(self.data.characters) do 271
232 local button = self.characterButtons[index] 272 button:SetSize(CP_HEADER_SIZE, CP_HEADER_SIZE)
233 if not button then 273 button.profileKey = key
234 button = CreateFrame('Button', nil, self, 'ClassOrderPlanCharacterButton') 274 button.className = info.className
235 button:SetID(index) 275 button.classColor = info.classColor
236 self.characterButtons[index] = button 276 button.characterName = info.characterName
237 277 button.characterRealm = info.characterRealm
238 if not self.lastButton then 278 button.showItems = info.showItems
239 button:SetPoint('BOTTOMLEFT', self, 'TOPLEFT', 0, 0) 279 button.isMine = (info == self.profile)
240 else 280 button:Update()
241 button:SetPoint('BOTTOMLEFT', self.lastButton, 'BOTTOMRIGHT', 2, 0) 281 button:Show()
242 end 282 index = index + 1
243 self.lastButton = button 283 end
244 end 284
245 if not profile.characterName then 285 self.HeaderInset:SetHeight(CP_HEADER_SIZE)
246 profile.characterName, profile.characterRealm = id:match("%(.+)%-(.+)^") 286 self.HeaderInset:ClearAllPoints()
247 end 287 self.HeaderInset:SetPoint('TOPLEFT' ,self, 'TOPLEFT')
248 288 self.HeaderInset:SetPoint('RIGHT' ,self, 'RIGHT')
249 button.className = profile.className 289 self.ClassStripe:ClearAllPoints()
250 button.classColor = profile.classColor 290 self.ClassStripe:SetPoint('TOPLEFT', self.HeaderInset, 'BOTTOMLEFT', 0, 0)
251 button.characterName = profile.characterName 291 self.ClassStripe:SetPoint('RIGHT')
252 button.characterRealm = profile.characterRealm 292 self:Reanchor()
253 button.hideItems = (profile.showItems == false) and (profile ~= self.profile) 293 self.isStale = nil
254 button.isMine = (profile == self.profile) 294 end
255 button:Update()
256 button:Show()
257 index = index + 1
258 end
259
260
261 self.isStale = nil
262 self:Reanchor()
263 self:SetHeight(self.currentHeight + CP_HEADER_SIZE)
264 end
265 295
266 296
267 function ClassPlan:Toggle() 297 function ClassPlan:Toggle()
268 if self:IsShown() then 298 if self:IsShown() then
269 self:Hide() 299 self.FadeOut:Play()
270 else 300 else
271 self:Show() 301 self.data.IsShown = true
272 end 302 self.FadeIn:Play()
273 303 end
274 if self.data then 304 end
275 self.data.IsShown = self:IsShown() 305
276 end
277 end
278 306
279 function ClassPlan:OnUpdate() 307 function ClassPlan:OnUpdate()
280 if self.isStale then 308 if self.requestingData then
281 print('|cFFFF4400An illusion! What are you hiding?|r') 309 self:RefreshData()
310 elseif self.isStale then
311 -- shouldn't happen, usually
282 self:Update() 312 self:Update()
283 end 313 end
314 if #self.ReportChunks >= 1 then
315 db.print(table.concat(self.ReportChunks, ', '))
316 wipe(self.ReportChunks)
317 end
318
284 end 319 end
285 320
286 function ClassPlan:OnShow() 321 function ClassPlan:OnShow()
287 print('|cFF00FFFFShow()') 322 print('|cFF00FFFFShow()')
288 if self.isStale then 323 self.isStale = true
289 self:Update()
290 end
291 self:Reanchor() 324 self:Reanchor()
292 end 325 end
293 326
294 function ClassPlan:OnHide() 327 function ClassPlan:OnHide()
295 print('|cFF00FFFFHide()') 328 print('|cFF00FFFFHide()')
296 end 329 end
297 330
298 function ClassPlan:Reanchor() 331 function ClassPlan:Reanchor()
332 if not (self.data.positionX and self.data.positionY) then
333 self.data.positionX = 0
334 self.data.positionY = -148
335 end
299 self:ClearAllPoints() 336 self:ClearAllPoints()
300 self:SetPoint('CENTER', self.data.positionX, self.data.positionY) 337 self:SetPoint('TOP', self.data.positionX, self.data.positionY)
301 338 self.currentHeight = 0
302 for index, frame in ipairs(self.Handlers) do 339 for index, frame in ipairs(self.Handlers) do
303 frame:Reanchor() 340 frame:Reanchor()
304
305 local ListTab = frame.ListTab 341 local ListTab = frame.ListTab
306 if ListTab then 342 if ListTab then
307 ListTab:ClearAllPoints() 343 ListTab:ClearAllPoints()
308 ListTab:SetPoint('TOPLEFT', frame, 'TOPLEFT', 0, CP_HEADER_SIZE) 344 ListTab:SetPoint('TOPLEFT', frame, 'TOPLEFT', 0, 0)
309 ListTab:SetPoint('BOTTOMRIGHT', frame, 'TOPRIGHT', 0, 0) 345 ListTab:SetPoint('BOTTOMRIGHT', frame, 'TOPRIGHT', 0, -CP_HEADER_SIZE)
310 ListTab.Label:SetText(frame.listTitle[frame.currentListIndex]) 346 ListTab.Label:SetText(frame.listTitle[frame.currentListIndex])
311 ListTab:Show() 347 ListTab:Show()
312 print(ListTab:GetSize()) 348 print(ListTab:GetSize())
313 end 349 end
314 350 self.currentHeight = max(self.currentHeight, frame.currentHeight or 0)
315 end 351 end
352 self:SetHeight(self.currentHeight + self.HeaderInset:GetHeight() + self.ClassStripe:GetHeight())
353
316 end 354 end
317 355
318 function ClassPlan:OnDragStart() 356 function ClassPlan:OnDragStart()
319 self:StartMoving() 357 self:StartMoving()
320 end 358 end
321 function ClassPlan:OnDragStop() 359 function ClassPlan:OnDragStop()
322
323 self:StopMovingOrSizing() 360 self:StopMovingOrSizing()
324 local x,y = self:GetCenter() 361 local x,y = self:GetCenter()
325 if x and y then 362 if x and y then
326 x = (x - GetScreenWidth()/2) 363 x = (x - GetScreenWidth()/2)
327 y = (y - GetScreenHeight()/2) * -1 364 y = (y - GetScreenHeight()/2) * -1
328 self.data.positionX, self.data.positionY = x,y 365 self.data.positionX, self.data.positionY = x,y
329 print('saving positions:', x, y) 366 print('saving positions:', x, y)
330 end 367 end
331 end 368 end
332 369
333 function SharedHandlers:SetList(index) 370 function ClassPlanHandlerBase:ScheduleUpdate(expires)
371 -- value will occasionally lag so check here
372 local duration = expires - time()
373 self.Timers = self.Timers or {}
374 if (duration > 0) and (not self.Timers[expires]) then
375 print(' adding timer at', expires, 'c', duration)
376 self.Timers[expires] = true
377 C_Timer.After(duration, function()
378 self.isStale = true
379 self:UpdateItems()
380 self.Timers[expires] = nil
381 end)
382 end
383 end
384
385 function ClassPlanHandlerBase:SetList(index)
386 local prevIndex = self.currentListIndex
334 if not index then 387 if not index then
335 if self.currentListIndex == #self.listKey then 388 if self.currentListIndex == #self.listKey then
336 index = 1 389 index = 1
337 else 390 else
338 index = self.currentListIndex + 1 391 index = self.currentListIndex + 1
339 end 392 end
340 end 393 end
341 394
342 print('|cFF0088FF'..self:GetName()..'|r:SetList()', index) 395 print('|cFF0088FF'..self:GetName()..'|r:SetList()', index, self.listKey[index])
343 self.currentListIndex = index 396 self.currentListIndex = index
344 self.activeKey = self.listKey[index] 397 self.activeKey = self.listKey[index]
345 self.activeTitle = self.listTitle[index] 398 self.activeTitle = self.listTitle[index]
346 399
400 self.ListTab.Label:SetText(self.listTitle[index])
347 self.isStale = true 401 self.isStale = true
348 end 402
349 403 if self.OnSetList then
350 function SharedHandlers:OnMouseWheel(delta) 404 self:OnSetList(self.currentListIndex, prevIndex)
405 end
406 end
407
408 function ClassPlanHandlerBase:OnMouseWheel(delta)
351 self.scrollOffset = (self.scrollOffset or 0) - ((delta > 0) and 1 or -1) 409 self.scrollOffset = (self.scrollOffset or 0) - ((delta > 0) and 1 or -1)
352 self:UpdateItems() 410 self:UpdateItems()
353 end 411 end
354 412
355 function SharedHandlers:RequestData() 413 function ClassPlanHandlerBase:RefreshData()
356 print('|cFF0088FF'..self:GetName()..':RequestData()') 414 print('|cFF0088FF'..self:GetName()..':RefreshData()')
415 local activeKey = self.activeKey
416 local detailsFailed
417 self.truncatedItems = 0
418 self.currentTime = time()
419 if self:GetParent().profile then
420 self:GetPlayerData()
421 else
422 detailsFailed = true
423 end
424 for _, listKey in ipairs(self.listKey) do
425 local sortedItems = self.sortedItems[listKey]
426 wipe(sortedItems)
427 for key, profile in pairs(self.data.characters) do
428 local isMine = (profile == self.profile)
429 print(key, listKey, isMine, profile.showItems)
430 local profileList = profile[listKey]
431 if profileList and #profileList >= 1 then
432 local classColor = profile.classColor or RAID_CLASS_COLORS['HUNTER']
433 if profile.showItems then
434 for index, data in ipairs(profileList) do
435 data.classColor = classColor
436 data.profileKey = key
437 data.isMine = isMine
438 if self.OnGetItem then
439 self:OnGetItem(data)
440 end
441 tinsert(sortedItems, data)
442 end
443 else
444 self.truncatedItems = self.truncatedItems + 1
445 end
446 end
447 end
448
449 if self.SortHandler then
450 sort(sortedItems, self.SortHandler)
451 end
452 end
453
454 for k,v in pairs(self.sortedItems) do
455 print(' ', k)
456 end
457
357 self.isStale = true 458 self.isStale = true
358 end 459 end
359 460
360 function SharedHandlers:OnEvent(event, arg) 461 function ClassPlanHandlerBase:OnEvent(event, id)
361 if (event == 'GARRISON_MISSION_LIST_UPDATE') and (arg ~= LE_FOLLOWER_TYPE_GARRISON_7_0) then 462 if (event == 'GARRISON_MISSION_LIST_UPDATE') then
362 -- ignore non-OrderHall updates 463 if (id == LE_FOLLOWER_TYPE_GARRISON_7_0) then
363 return 464 print('|cFF00FF88'..self:GetName()..':OnEvent()|r', event, id)
364 end 465 self:RefreshData()
365 print('|cFF00FF88'..self:GetName()..':OnEvent()|r', event, arg) 466 end
366 if self:IsVisible() then
367 print('|cFF88FF00 frame visible; get busy')
368 self:RequestData()
369 else 467 else
370 if not self.NextData then 468 print('|cFF00FF88'..self:GetName()..':OnEvent()|r', event, id)
371 print('|cFF88FF00 setting timer') 469 end
372 self.NextData = C_Timer.NewTimer(0.25, function() 470 end
373 if self.initialized then 471
374 self:RequestData() 472 function ClassPlanHandlerBase:OnUpdate()
375 self.NextData:Cancel()
376 self.NextData = nil
377 print('|cFF88FF00'..self:GetName()..' clearing timer')
378 end
379
380 end)
381 end
382 end
383 end
384 function SharedHandlers:OnUpdate()
385 if self.isStale then 473 if self.isStale then
386 self:GetParent():Update() 474 print('|cFF00FF00'..self:GetName()..':OnUpdate()|r')
387 end 475
388 end 476 self:UpdateItems()
389 477 end
478 end
390 479
391 -- Stuff set on every list item 480 -- Stuff set on every list item
392 function SharedHandlers:SetOwnerData (self, data) 481 function ClassPlanHandlerBase:SetOwnerData (self, data)
393 local name, realm = string.match(data.profileKey, "(.+)%-(.+)") 482 local name, realm = string.match(data.profileKey, "(.+)%-(.+)")
394 local ownerText = '|c'.. data.classColor.colorStr .. name .. '|r' 483 local ownerText = '|c'.. data.classColor.colorStr .. name .. '|r'
395 self.Owner:SetText(ownerText) 484 self.Owner:SetText(ownerText)
396 self.Name:SetText(self.name) 485 self.Name:SetText(self.name)
397 self.Name:SetTextColor(data.classColor.r, data.classColor.g, data.classColor.b) 486 self.Name:SetTextColor(data.classColor.r, data.classColor.g, data.classColor.b)
398 end 487 end
399 488
400 function SharedHandlers:Acquire(id) 489 function ClassPlanHandlerBase:Acquire(id)
401 end 490 end
402 function SharedHandlers:FreeBlock (block) 491 function ClassPlanHandlerBase:FreeBlock (block)
403 end 492 end
404 493
405 function SharedHandlers:UpdateItems() 494 function ClassPlanHandlerBase:UpdateItems()
406 495 print('|cFF0088FF '..self:GetName()..':UpdateItems()|r', self.activeKey)
407 self.MoreItemsUp:Hide() 496 self.MoreItemsUp:Hide()
408 self.MoreItemsDown:Hide() 497 self.MoreItemsDown:Hide()
409 498 local sortedItems = self.sortedItems[self.activeKey]
410 local sortedItems = self.sortedItems
411 local scrollOffset = self.scrollOffset or 0 499 local scrollOffset = self.scrollOffset or 0
412 local numItems = #sortedItems 500 local numItems = #sortedItems
413 if (not sortedItems[scrollOffset+1]) or (numItems <= self.maxItems) then 501 if (not sortedItems[scrollOffset+1]) or (numItems <= self.maxItems) then
414 scrollOffset = 0 502 scrollOffset = 0
415 elseif (numItems > self.maxItems) and (scrollOffset > (numItems - self.maxItems)) then 503 elseif (numItems > self.maxItems) and (scrollOffset > (numItems - self.maxItems)) then
416 scrollOffset = (numItems - self.maxItems) 504 scrollOffset = (numItems - self.maxItems)
417 end 505 end
418 506
419 507 self.ListTab.Count:SetText(numItems)
420 self.blocks = self.blocks or {} 508 self.blocks = self.blocks or {}
421 local blocks = self.blocks 509 local blocks = self.blocks
422
423 local lastProfile 510 local lastProfile
424 local totalHeight = 0 511 local totalHeight = (self.ListTab:GetHeight() or 0)
425 self.lastBlock = nil 512 self.lastBlock = nil
426 self.numActive = 0 513 self.numActive = 0
427 for i = 1, self.maxItems do 514 for i = 1, self.maxItems do
428 local index = scrollOffset + i 515 local index = scrollOffset + i
429 local data = sortedItems[index] 516 local data = sortedItems[index]
430 if not data then 517 if not data then
518 print('|cFFFF4400end of data')
431 break 519 break
432 end 520 end
433
434 521
435 local block = blocks[i] 522 local block = blocks[i]
436 if not block then 523 if not block then
437 block = CreateFrame('Button', nil, self, self.templateName) 524 block = CreateFrame('Button', self:GetName()..'ListItem'..i , self, self.templateName)
438 block.listType = self.activeKey 525 block.listType = self.activeKey
526
527 block.doAnimation = true
528
439 block.handler = self 529 block.handler = self
440 self.numBlocks = self.numBlocks + 1 530 self.numBlocks = self.numBlocks + 1
441 blocks[i] = block 531 blocks[i] = block
442 end 532 end
443 block:SetID(index) 533 block:SetID(index)
444
445 print('RefreshItem', block)
446 self.numActive = self.numActive + 1 534 self.numActive = self.numActive + 1
447 535
448 if self.lastBlock then 536 if self.lastBlock then
449 block:SetPoint('TOPLEFT', self.lastBlock, 'BOTTOMLEFT', 0, 0) 537 block:SetPoint('TOPLEFT', self.lastBlock, 'BOTTOMLEFT', 0, 0)
450 print('--', index, data.isComplete, data.missionEndTime, data.name) 538 --print('--', index, data.isComplete, data.missionEndTime, data.name)
451 else 539 else
452 block:SetPoint('TOPLEFT', 0, 0) 540 block:SetPoint('TOPLEFT', self.ListTab, 'BOTTOMLEFT', 0, 0)
453 print('--top') 541 --print('--top')
454 end 542 end
455 self.lastBlock = block 543 self.lastBlock = block
456 544
457 totalHeight = totalHeight + block:GetHeight() 545 totalHeight = totalHeight + block:GetHeight()
458 block.lastProfile = lastProfile 546 block.lastProfile = lastProfile
489 if blocks[i] then 577 if blocks[i] then
490 blocks[i]:Hide() 578 blocks[i]:Hide()
491 end 579 end
492 end 580 end
493 581
582 self:Reanchor()
583 if totalHeight ~= self.currentHeight then
584 self.currentHeight = totalHeight
585 self:SetHeight(self.currentHeight)
586 self:GetParent():Reanchor()
587 end
588
589
494 self.scrollOffset = scrollOffset 590 self.scrollOffset = scrollOffset
495 self:Reanchor() 591 self.isStale = nil
496
497 return totalHeight 592 return totalHeight
498 end 593 end
499 594
500 595 function ClassPlanEntryBase:OnAnimFinished()
501 function ShipmentList:Reanchor() 596 end
502 print('|cFF00FFFF'..self:GetName()..':Reanchor|r') 597 function ClassPlanEntryBase:OnShow()
503 self:SetPoint('TOPLEFT', 0, -24) 598
504 self:SetPoint('BOTTOMRIGHT', -ClassOrderPlan:GetWidth()/2, 0) 599 print('|cFF44FF00'..self:GetName()..':OnShow()')
505 end 600 if self.doAnimation then
506 601 self.doAnimation = nil
507 602 if not ClassOrderPlan.isAnimating then
508 603 self.NewBlockFade:Play()
509 do 604 end
510 local ShipmentsInfo = {} 605 end
511 local AddShipmentInfo = function(shipmentType, name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID, followerID) 606 end
512 -- early login queries may return empty tables, causing the sorter to compare nil 607
513 if not creationTime then 608 function ClassPlanEntryBase:SetTimeLeft(expires, duration)
514 return
515 end
516 --print(shipmentType, name, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString)
517 tinsert(ShipmentsInfo,
518 {
519 shipmentType = shipmentType,
520 name = name,
521 icon = texture,
522 shipmentCapacity = shipmentCapacity,
523 shipmentsReady = shipmentsReady,
524 shipmentsTotal = shipmentsTotal,
525 creationTime = creationTime,
526 duration = duration,
527 timeleftString = timeleftString,
528 itemName = itemName,
529 itemIcon = itemIcon,
530 itemQuality = itemQuality,
531 itemID = itemID,
532 followerID = followerID,
533 })
534 end
535 function ShipmentList:GetPlayerData (profile)
536 if not profile then
537 return false
538 end
539 local profileList = profile.shipments
540 wipe(ShipmentsInfo)
541
542 local garrisonType = LE_GARRISON_TYPE_7_0
543 local buildings = CG_GetBuildings(garrisonType);
544 local shipmentIndex = 0
545 --print('Buildings:')
546 for i = 1, #buildings do
547 local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID = CG_GetLandingPageShipmentInfo(buildingID);
548 AddShipmentInfo('Building', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID)
549 end
550
551 --print('Follower:')
552 local followerShipments = CG_GetFollowerShipments(garrisonType);
553 for i = 1, #followerShipments do
554 local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, _, _, _, _, followerID = CG_GetLandingPageShipmentInfoByContainerID(followerShipments[i]);
555 AddShipmentInfo('Follower', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, nil, nil, nil, nil, followerID)
556 end
557
558 --print('Loose:')
559 local looseShipments = CG_GetLooseShipments(garrisonType)
560 for i = 1, #looseShipments do
561 local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString = CG_GetLandingPageShipmentInfoByContainerID(looseShipments[i]);
562 AddShipmentInfo('Misc', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString)
563 end
564
565 local talentTrees = CG_GetTalentTrees(garrisonType, select(3, UnitClass("player")));
566 -- this is a talent that has completed, but has not been seen in the talent UI yet.
567 local completeTalentID = CG_GetCompleteTalent(garrisonType);
568 --print('Talents:')
569 if (talentTrees) then
570 for treeIndex, tree in ipairs(talentTrees) do
571 for talentIndex, talent in ipairs(tree) do
572 local showTalent = false;
573 if (talent.isBeingResearched) or (talent.id == completeTalentID) then
574 AddShipmentInfo('Talent', talent.name, talent.icon, 1, (talent.isBeingResearched and 0 or 1), 1, talent.researchStartTime, talent.researchDuration, talent.timeleftString)
575 end
576 end
577 end
578 end
579
580 wipe(profileList)
581 for index, data in ipairs(ShipmentsInfo) do
582 --DEFAULT_CHAT_FRAME:AddMessage(data.shipmentType ..' '.. tostring(data.name) ..' '.. tostring(data.creationTime) ..' '.. tostring(data.duration))
583 tinsert(profileList, data)
584 end
585 self.isStale = true
586 return true
587 end
588 end
589
590
591 function SharedEntry:SetTimeLeft(expires, duration)
592 self.ProgressBG:Hide() 609 self.ProgressBG:Hide()
593 self.ProgressBar:Hide() 610 self.ProgressBar:Hide()
594 if not expires then 611 if not expires then
595 return 612 return
596 end 613 end
597 614
598 -- calculate here since time isn't available 615 -- calculate here since time isn't available
599 local timeLeft = expires - GI_currentTime 616 local timeLeft = expires - time()
600 if timeLeft < 0 then 617 if timeLeft < 0 then
601 -- handle being complete 618 -- handle being complete
602 619 if self.shipmentsReady and (self.shipmentsReady < self.shipmentsTotal) then
620 self.TimeLeft:SetText('Ready')
621 else
622 self.TimeLeft:SetText('Complete!')
623 end
603 else 624 else
604 self.TimeLeft:SetText(GetTimeLeftString(timeLeft)) 625 self.TimeLeft:SetText(GetTimeLeftString(timeLeft))
605 end 626 end
606 627
607 if (timeLeft > 0) and duration then 628 if (timeLeft > 0) and duration then
608 local progress = (duration - timeLeft) / duration 629 local progress = (duration - timeLeft) / duration
609 local r = ((progress >= .5) and (progress/2)) or 1 630 local r = ((progress >= .5) and (progress/2)) or 1
610 local g = ((progress <= .5) and (progress*2)) or 1 631 local g = ((progress <= .5) and (progress*2)) or 1
611 self.ProgressBG:Show() 632 self.ProgressBG:Show()
612 self.ProgressBar:Show() 633 self.ProgressBar:Show()
613
614 self.ProgressBG:SetColorTexture(r,g,0,0.25) 634 self.ProgressBG:SetColorTexture(r,g,0,0.25)
615 self.ProgressBar:SetColorTexture(r,g,0,0.5) 635 self.ProgressBar:SetColorTexture(r,g,0,0.5)
616 self.ProgressBar:SetWidth(self:GetWidth() * progress) 636 self.ProgressBar:SetWidth(self.ProgressBG:GetWidth() * progress)
617 end 637 end
618 end 638 end
619 639
620 -- Update shipment flags data 640
621 local SetActualShipmentTime = function(self) 641
622 642 ClassPlanHeaderMixin = {}
623 if self.isComplete then 643 function ClassPlanHeaderMixin:OnLoad()
624 return nil, nil 644 self:EnableMouse((#self:GetParent().listKey > 1))
625 end 645 self:RegisterForClicks('AnyUp')
626 646 end
627 local timestamp = time() 647 function ClassPlanHeaderMixin:OnClick ()
628 local timeLeft = self.creationTime + self.duration - timestamp 648 local frame = self:GetParent()
629 local duration = self.duration * self.shipmentsTotal 649 frame:SetList()
630 local justFinished = false 650 if frame.OnHeaderClick then
631 while (self.shipmentsReady < self.shipmentsTotal) and (timeLeft <= 0) do 651 frame.OnHeaderClick(frame)
632 if not self.originalReady then 652 end
633 self.originalReady = self.shipmentsReady 653 end
634 self.originalCreationTime = self.creationTime 654
635 end 655 ClassPlanCharacterButtonMixin = {
636 656 }
637 657 function ClassPlanCharacterButtonMixin:Update ()
638 self.shipmentsReady = self.shipmentsReady + 1 658 --print(CLASS_ICON_TCOORDS[self.className:upper()])
639 self.creationTime = self.creationTime + self.duration 659 if self.className and CLASS_ICON_TCOORDS[self.className:upper()] then
640 timeLeft = timeLeft + self.duration 660 self.Icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[self.className:upper()]))
641 print('|cFF00FF88udpating '..self.name..'|r', 'timeLeft:', timeLeft, 'shipments:', self.shipmentsReady, self.shipmentsTotal) 661 end
642 end 662 self.Icon:SetDesaturated((not self.showItems))
643 663 self.SelectGlow:SetShown(self.isMine)
644 if (timeLeft <= 0) and (not self.isBeingResearched) then 664 end
645 self.isComplete = true 665
646 self.isStale = true 666 function ClassPlanCharacterButtonMixin:OnEnter()
647 end 667 if not self.profileKey then
648
649
650 local expires = (self.originalCreationTime or self.creationTime) + duration
651
652 return expires, duration
653 end
654
655 function ShipmentList:OnGetItem (data)
656 print('OnGetItem()')
657 if data.shipmentsTotal then
658 SetActualShipmentTime(data)
659 end
660 end
661
662 ShipmentList.SortHandler = function(a, b)
663 if b.isComplete ~= a.isComplete then
664 return a.isComplete and true or false
665 elseif a.shipmentsReady or b.shipmentsReady then
666 return (a.shipmentsReady or 0) > (b.shipmentsReady or 0)
667 else
668 return (a.creationTime) < (b.creationTime)
669 end
670 end
671
672 function ShipmentList:OnLoad()
673 C_Garrison.RequestLandingPageShipmentInfo();
674 end
675 function ShipmentList:OnShow()
676 print('|cFF00FF88'..self:GetName()..':OnShow()|r')
677 C_Garrison.RequestLandingPageShipmentInfo()
678 end
679
680 function ShipmentEntry:OnLoad()
681 MissionEntry.OnLoad(self)
682 end
683
684
685 function ShipmentEntry:Update()
686 print('|cFF0088FF'.. self.name..'|r:Update()')
687 self.Icon:SetTexture(self.icon)
688 self.Count:SetText(self.shipmentsReady)
689 self.Done:SetShown(self.shipmentsReady and (self.shipmentsReady >= 1))
690
691 -- flag as complete
692
693 local bgColor = CP_BACKGROUND_COLOR.inProgress
694 if ( self.shipmentsReady >= self.shipmentsTotal ) and (not self.isBeingResearched) then
695 self.Swipe:SetCooldownUNIX(0, 0);
696 self.Done:Show();
697 bgColor = CP_BACKGROUND_COLOR.complete
698 else
699 if (self.shipmentsReady >= 1) and (self.shipmentsReady < self.shipmentsTotal) then
700 bgColor = CP_BACKGROUND_COLOR.shipmentsReady
701 end
702 self.Swipe:SetCooldownUNIX(self.creationTime or 0 , self.duration or 0);
703 end
704 self.Background:SetColorTexture(unpack(bgColor))
705
706 SetActualShipmentTime(self)
707
708 if self.originalReady then
709 print('|cFF00FF88'..self.name..'|r', 'starting ready:', self.originalReady, 'starting time:', self.originalCreationTime)
710 end
711 end
712
713 function ShipmentEntry:OnUpdate(sinceLast)
714 self.throttle = (self.throttle or 1) + sinceLast
715 if self.throttle >= 1 then
716 self.throttle = self.throttle - 1
717 else
718 return 668 return
719 end 669 end
720 670
721 671 GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
722 if (self.shipmentsReady and self.shipmentsTotal) and (self.shipmentsReady < self.shipmentsTotal) then 672 local info = ClassOrderPlan.data.characters[self.profileKey]
723 local expires, duration = SetActualShipmentTime(self) 673 GameTooltip:AddLine(self.characterName, self.classColor.r, self.classColor.g, self.classColor.b)
724 674 local numItems = 0
725 if self.isComplete then 675 if info.missions then
726 self.TimeLeft:SetText('Complete!') 676 GameTooltip:AddLine(#info.missions .. ' mission'..((#info.missions == 1) and '' or 's')..' in progress')
727 self.TimeLeft:SetTextColor(0,1,1) 677 end
728 elseif self.shipmentsReady >= 1 then 678 if info.shipments then
729 self:SetTimeLeft(expires, duration) 679 GameTooltip:AddLine(#info.shipments .. ' work order' .. ((#info.shipments == 1) and '' or 's'))
730 self.TimeLeft:SetTextColor(0,1,0) 680 end
731 else 681 if info.available then
732 self:SetTimeLeft(expires, duration) 682 GameTooltip:AddLine(#info.available .. ' mission'..((#info.available == 1) and '' or 's')..' available')
733 self.TimeLeft:SetTextColor(1,1,1) 683 end
734 end 684 GameTooltip:Show()
735 685 end
736 elseif self.isBeingResearched then 686
737 self:SetTimeLeft(self.researchStartTime + self.researchDuration - time(), self.researchDuration) 687 function ClassPlanCharacterButtonMixin:OnLeave()
738 self.TimeLeft:SetTextColor(1,1,1)
739 else
740 self.TimeLeft:SetText('Complete!')
741 self.TimeLeft:SetTextColor(0,1,0)
742 end
743
744 end
745
746 function ShipmentEntry:OnEnter()
747 if ( self.shipmentsReady and self.shipmentsTotal ) then
748 GameTooltip:SetOwner(self, 'ANCHOR_LEFT')
749 GameTooltip:AddLine(self.Owner:GetText(), self.Owner:GetTextColor())
750 GameTooltip:AddLine(self.shipmentType)
751 GameTooltip:AddLine(self.shipmentsReady .. ' of '.. self.shipmentsTotal)
752 GameTooltip:Show()
753 end
754 end
755
756 function ShipmentEntry:OnLeave()
757 if GameTooltip:IsOwned(self) then 688 if GameTooltip:IsOwned(self) then
758 GameTooltip:Hide() 689 GameTooltip:Hide()
759 end 690 end
760 end 691 end
761 692
762 function ShipmentEntry:OnClick(button) 693 function ClassPlanCharacterButtonMixin:OnClick(button, down)
694 print('OnClick', self.profileKey)
695 local clist = ClassOrderPlan.data.characters
696
763 if button == 'RightButton' then 697 if button == 'RightButton' then
764 self.handler:FreeBlock(self) 698 for _, profile in pairs(clist) do
765 end 699 profile.showItems = true
766 end 700 end
767 701 else
768 702 if clist[self.profileKey].showItems then
769 703 clist[self.profileKey].showItems = nil
770 704 else
771 ClassPlanMissionHandler = Mixin(MissionList, SharedHandlers) 705 clist[self.profileKey].showItems = true
772 ClassPlanMissionEntryMixin = Mixin(MissionEntry, SharedEntry) 706 end
773 ClassPlanShipmentHandler = Mixin(ShipmentList, SharedHandlers) 707 end
774 ClassPlanShipmentEntryMixin = Mixin(ShipmentEntry,SharedEntry) 708 for i, handler in ipairs(ClassOrderPlan.Handlers) do
775 709 handler.isStale = true
776 ClassPlanHeaderMixin = { 710 end
777 OnClick = function(self) 711
778 self:GetParent():SetList() 712 ClassOrderPlan:RefreshData()
779 self:GetParent().isStale = true 713 ClassOrderPlan:Update()
780 ClassOrderPlan:Update() 714 print(clist[self.profileKey].showItems)
781 end 715 end
782 }
783
784 ClassPlanCharacterButtonMixin = {
785 Update = function(self)
786 print(CLASS_ICON_TCOORDS[self.className:upper()])
787 if self.className and CLASS_ICON_TCOORDS[self.className:upper()] then
788 self.Icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[self.className:upper()]))
789 end
790 self.Icon:SetDesaturated(self.showItems)
791 self.SelectGlow:SetShown(self.isMine)
792 end
793 }
794
795 function ClassPlanCharacterButtonMixin:OnEnter() end
796 function ClassPlanCharacterButtonMixin:OnLeave() end
797 function ClassPlanCharacterButtonMixin:OnClick() end