Mercurial > wow > worldplan
comparison QuestPOI.lua @ 29:c1612c2c1840
WorldPlan:
- Optimizations to in a lot of areas that should lead to better load-times and snappier world map.
* Responding to quest log and map events by setting flags instead of tailing into the complete works.
* Using a generic getter function for resolving pin visual attributes. and making use of blizzard constants for sanity's sake.
author | Nenue |
---|---|
date | Thu, 27 Oct 2016 13:50:56 -0400 |
parents | 4a7e89bffbcb |
children | 8cb750e79952 |
comparison
equal
deleted
inserted
replaced
28:3f4368c4a49b | 29:c1612c2c1840 |
---|---|
1 -- WorldPlan | 1 -- WorldPlan |
2 -- QuestPOI.lua | 2 -- QuestPOI.lua |
3 -- Created: 10/1/2016 7:21 PM | 3 -- Created: 10/1/2016 7:21 PM |
4 -- %file-revision% | 4 -- %file-revision% |
5 -- | 5 -- |
6 | |
7 local TQ_GetQuestInfoByQuestID = C_TaskQuest.GetQuestInfoByQuestID -- Return the name of a quest with a given ID | |
6 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation | 8 local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation |
7 local TQ_GetQuestTimeLeftMinutes = C_TaskQuest.GetQuestTimeLeftMinutes | 9 local TQ_GetQuestTimeLeftMinutes = C_TaskQuest.GetQuestTimeLeftMinutes |
8 local TQ_IsActive = C_TaskQuest.IsActive | 10 local TQ_IsActive = C_TaskQuest.IsActive |
11 local TQ_RequestPreloadRewardData = C_TaskQuest.RequestPreloadRewardData | |
9 local QuestPOIGetIconInfo, WorldMapPOIFrame = QuestPOIGetIconInfo, WorldMapPOIFrame | 12 local QuestPOIGetIconInfo, WorldMapPOIFrame = QuestPOIGetIconInfo, WorldMapPOIFrame |
10 | 13 |
11 local print = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end | 14 local print = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end |
12 local qprint = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or function() end | 15 local qprint = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or function() end |
16 local wqprint = DEVIAN_WORKSPACE and function(...) _G.print('WorldQuest', ...) end or function() end | |
13 local iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or function() end | 17 local iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or function() end |
14 local QuestPOI = WorldPlanPOIMixin | 18 local QuestPOI = WorldPlanPOIMixin |
15 | 19 |
16 local ICON_UNKNOWN = "Interface\\ICONS\\inv_misc_questionmark" | 20 local ICON_UNKNOWN = "Interface\\ICONS\\inv_misc_questionmark" |
17 local ICON_MONEY = "Interface\\Buttons\\UI-GroupLoot-Coin-Up" | 21 local ICON_MONEY = "Interface\\Buttons\\UI-GroupLoot-Coin-Up" |
20 local POI_BORDER_FILL = "Interface\\BUTTONS\\YELLOWORANGE64" | 24 local POI_BORDER_FILL = "Interface\\BUTTONS\\YELLOWORANGE64" |
21 local POI_BORDER_BLUE = "Interface\\BUTTONS\\GRADBLUE" | 25 local POI_BORDER_BLUE = "Interface\\BUTTONS\\GRADBLUE" |
22 local POI_BORDER_RED = "Interface\\BUTTONS\\RedGrad64" | 26 local POI_BORDER_RED = "Interface\\BUTTONS\\RedGrad64" |
23 local POI_BORDER_YELLOW = "Interface\\BUTTONS\\YELLOWORANGE64" | 27 local POI_BORDER_YELLOW = "Interface\\BUTTONS\\YELLOWORANGE64" |
24 local POI_BORDER_GREEN = "Interface\\BUTTONS\\GREENGRAD64" | 28 local POI_BORDER_GREEN = "Interface\\BUTTONS\\GREENGRAD64" |
29 | |
30 local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD | |
31 local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER | |
32 local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT | |
33 local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES | |
34 local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS | |
35 | |
36 | |
37 local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP | |
38 local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE | |
39 local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON | |
40 local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION | |
41 local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL | |
42 | |
43 local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP | |
44 local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE | |
45 local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON | |
46 local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION | |
47 local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL | |
48 | |
49 -- Pin color/display variables | |
25 | 50 |
26 local familiars = { | 51 local familiars = { |
27 [42159] = {npc = 106552, name = 'Nightwatcher Merayl'}, | 52 [42159] = {npc = 106552, name = 'Nightwatcher Merayl'}, |
28 [40277] = {npc = 97804, name = 'Tiffany Nelson'}, | 53 [40277] = {npc = 97804, name = 'Tiffany Nelson'}, |
29 [40298] = {npc = 99182, name = 'Sir Galveston'}, | 54 [40298] = {npc = 99182, name = 'Sir Galveston'}, |
41 [40279] = {npc = 99035, name = 'Durian Strongfruit'} | 66 [40279] = {npc = 99035, name = 'Durian Strongfruit'} |
42 } | 67 } |
43 local familiars_id = 9696 | 68 local familiars_id = 9696 |
44 | 69 |
45 | 70 |
46 local PIN_TIME_CONTEXT = { | |
47 {max = 60, | |
48 r=1, g=0.25, b =0, format = function (minutes) return '|cFFFF4400'.. minutes .. 'm' end, | |
49 continentAlpha = 1, swipeTime = 1440, | |
50 }, | |
51 {max = 240, | |
52 r=1, g=.5, b=0, format = function(minutes) return '|cFFFF4400'.. floor(minutes/60) .. 'h' end, | |
53 continentAlpha = 1, swipeTime = 1440, | |
54 }, | |
55 {max = 1440, | |
56 r=1, g=1, b=0, format = function(minutes) return '|cFFFFFF00'.. floor(minutes/60) .. 'h' end, | |
57 continentAlpha = .55, swipeTime = 1440 | |
58 }, | |
59 {max = 10081, | |
60 r=0, g=1, b=0, | |
61 continentAlpha = .3, | |
62 }, -- 7 days + 1 minute | |
63 } | |
64 | |
65 -- update a masked texture without messing up its blending mask | 71 -- update a masked texture without messing up its blending mask |
66 local SetMaskedTexture = function(region, file, mask) | 72 local SetMaskedTexture = function(region, file, mask) |
67 mask = mask or POI_BORDER_MASK | 73 mask = mask or POI_BORDER_MASK |
68 region:SetMask(nil) | 74 region:SetMask(nil) |
69 region:SetTexture(file) | 75 region:SetTexture(file) |
70 region:SetMask(mask) | 76 region:SetMask(mask) |
77 end | |
78 | |
79 | |
80 -- use tooltip object to extract item details | |
81 local ParseItemReward = function(questID) | |
82 local name, icon, quantity, quality, _, itemID = GetQuestLogRewardInfo(1, questID) | |
83 local scanner = _G.WorldPlanTooltip | |
84 if not itemID then | |
85 return | |
86 end | |
87 | |
88 scanner:SetOwner(WorldPlan, "ANCHOR_NONE") | |
89 scanner:SetItemByID(itemID) | |
90 scanner:Show() | |
91 local ttl1 = _G['WorldPlanTooltipTextLeft1'] | |
92 local ttl2 = _G['WorldPlanTooltipTextLeft2'] | |
93 local ttl3 = _G['WorldPlanTooltipTextLeft3'] | |
94 local ttl4 = _G['WorldPlanTooltipTextLeft4'] | |
95 if ttl2 then | |
96 local text = ttl2:GetText() | |
97 -- Artifact Power | |
98 if text then | |
99 if text:match("|cFFE6CC80") then | |
100 --print('AP token!', text) | |
101 local power | |
102 if ttl4 then | |
103 local text = ttl4:GetText() | |
104 --print('tip line 4', text) | |
105 if text then | |
106 power = text:gsub("%p", ""):match("%d+") | |
107 power = tonumber(power) | |
108 end | |
109 | |
110 end | |
111 return REWARD_ARTIFACT_POWER, "Interface\\ICONS\\inv_7xp_inscription_talenttome01", power, name, itemID | |
112 elseif text:match("Item Level") then | |
113 --print('equipment!', text) | |
114 quantity = text:match("Item Level ([%d\+]+)") | |
115 return REWARD_GEAR, icon, quantity, name, itemID | |
116 elseif text:match("Crafting Reagent") then | |
117 --print('|cFFFF4400it is a reagent', text) | |
118 return REWARD_REAGENT, icon, quantity, name, itemID | |
119 end | |
120 end | |
121 | |
122 elseif ttl3 then | |
123 local text = ttl3:GetText() | |
124 if text:match("Crafting Reagent") then | |
125 --print('|cFFFF4400it is a reagent', text) | |
126 return REWARD_REAGENT, icon, quantity, name, itemID | |
127 end | |
128 end | |
129 return 128, icon, quantity, name, itemID | |
71 end | 130 end |
72 | 131 |
73 function WorldPlanPOIMixin:OnEnter() | 132 function WorldPlanPOIMixin:OnEnter() |
74 local completed = select(4,GetAchievementInfo(familiars_id)) | 133 local completed = select(4,GetAchievementInfo(familiars_id)) |
75 if not completed then | 134 if not completed then |
104 function WorldPlanPOIMixin:OnMouseDown() | 163 function WorldPlanPOIMixin:OnMouseDown() |
105 TaskPOI_OnClick(self) | 164 TaskPOI_OnClick(self) |
106 end | 165 end |
107 | 166 |
108 | 167 |
168 | |
169 -- create or update the pin using the given questID and C_TaskQuest results | |
170 function WorldPlanPOIMixin:RefreshData (info) | |
171 | |
172 qprint('|cFF00FF88'..self:GetName()..':RefreshData()|r') | |
173 | |
174 if info then | |
175 | |
176 self.x = info.x or self.x | |
177 self.y = info.y or self.y | |
178 self.inProgress = info.inProgress | |
179 self.floor = info.floor | |
180 self.numObjectives = info.numObjectives or 0 | |
181 print('|cFFFF4400subbing in new info', info.x, info.y, self.x, self.y) | |
182 end | |
183 | |
184 | |
185 local questID = self:GetID() | |
186 local questTitle, rewardIcon, rewardName, rewardCount, rewardStyle, rewardType, itemID, quantity, quality, _ | |
187 local hasUpdate, isPending = self.isNew, false | |
188 | |
189 | |
190 if not HaveQuestData(questID) then | |
191 TQ_RequestPreloadRewardData(questID) | |
192 isPending = true | |
193 qprint('because not have data') | |
194 else | |
195 | |
196 -- set reward category | |
197 local numRewards = GetNumQuestLogRewards(questID) | |
198 local numCurrency = GetNumQuestLogRewardCurrencies(questID) | |
199 local money = GetQuestLogRewardMoney(questID) | |
200 if numRewards >= 1 then | |
201 rewardType, rewardIcon, rewardCount, rewardName, itemID = ParseItemReward(questID) | |
202 elseif numCurrency >= 1 then | |
203 rewardName, rewardIcon, rewardCount = GetQuestLogRewardCurrencyInfo(1, questID) | |
204 rewardType = REWARD_CURRENCY | |
205 elseif money >= 1 then | |
206 rewardIcon = ICON_MONEY | |
207 rewardName = GetMoneyString(money) | |
208 rewardType = REWARD_CASH | |
209 end | |
210 rewardStyle = WorldPlan:GetTypeInfo(rewardType) | |
211 | |
212 self.itemNumber = rewardCount or self.itemNumber | |
213 self.rewardType = rewardType or REWARD_ITEM | |
214 self.style = rewardStyle | |
215 | |
216 -- title, faction, capped state | |
217 local questTitle, factionID, capped = TQ_GetQuestInfoByQuestID(questID) | |
218 self.factionID = factionID | |
219 self.capped = capped | |
220 | |
221 -- set tag details | |
222 local tagID, tagName, worldQuestType, rarity, isElite, tradeskillLineIndex = GetQuestTagInfo(questID); | |
223 local tagAtlas | |
224 if worldQuestType == LE_QUEST_TAG_TYPE_PET_BATTLE then | |
225 tagAtlas = "worldquest-icon-petbattle" | |
226 elseif worldQuestType == LE_QUEST_TAG_TYPE_PVP then | |
227 tagAtlas = "worldquest-icon-pvp-ffa" | |
228 elseif worldQuestType == LE_QUEST_TAG_TYPE_PROFESSION then | |
229 local id = tradeskillLineIndex and select(7, GetProfessionInfo(tradeskillLineIndex)) | |
230 if id then | |
231 tagAtlas = WORLD_QUEST_ICONS_BY_PROFESSION[id] | |
232 end | |
233 elseif worldQuestType == LE_QUEST_TAG_TYPE_DUNGEON then | |
234 tagAtlas = "worldquest-icon-dungeon" | |
235 end | |
236 | |
237 self.tagID = tagID | |
238 self.tagName = tagName | |
239 self.worldQuestType = worldQuestType | |
240 self.isElite = isElite | |
241 self.tradeskillLineIndex = tradeskillLineIndex | |
242 self.rarity = rarity | |
243 self.tagAtlas = tagAtlas | |
244 | |
245 -- flag unresolved info | |
246 if not (rewardIcon and rewardName) then | |
247 isPending = true | |
248 qprint('because not have icon') | |
249 TQ_RequestPreloadRewardData (questID) | |
250 --WorldPlan:print('|cFFFFFF00'..tostring(self.title)..'|r waiting on texture info') | |
251 else | |
252 if (rewardIcon and rewardName) and isPending then | |
253 --WorldPlan:print('|cFF00FF00'..tostring(self.title)..'|r has info', rewardIcon, rewardName) | |
254 hasUpdate = true | |
255 end | |
256 isPending = false | |
257 end | |
258 | |
259 self.title = questTitle or "|cFFFF0000Retrieving..." | |
260 self.itemTexture = rewardIcon or self.itemTexture | |
261 self.itemName = rewardName or self.itemName | |
262 self.hasUpdate = hasUpdate | |
263 self.isPending = isPending | |
264 | |
265 | |
266 qprint(' |cFF00FFFF'..questID..'|r hasUpdate:', hasUpdate, 'isPending:', isPending) | |
267 qprint(' ', self.title, self.itemTexture, 'rewardType:', self.rewardType, 'tag:', self.tagID, 'style', self.style ) | |
268 end | |
269 return hasUpdate, isPending | |
270 end | |
271 | |
272 | |
109 function WorldPlanPOIMixin:SetAchievementProgressTooltip() | 273 function WorldPlanPOIMixin:SetAchievementProgressTooltip() |
110 print('cheevos') | 274 print('cheevos') |
111 | |
112 | |
113 end | 275 end |
114 | 276 |
115 function WorldPlanPOIMixin:ShowNew() | 277 function WorldPlanPOIMixin:ShowNew() |
116 self:SetShown(true) | 278 self:SetShown(true) |
117 self.isNew = nil | 279 self.isNew = nil |
131 function WorldPlanPOIMixin:OnHide() | 293 function WorldPlanPOIMixin:OnHide() |
132 qprint('|cFFFFFF00["'..tostring(self.title)..'"]|r:OnHide()') | 294 qprint('|cFFFFFF00["'..tostring(self.title)..'"]|r:OnHide()') |
133 end | 295 end |
134 | 296 |
135 function WorldPlanPOIMixin:SetAnchor(frame, mapID, mapWidth, mapHeight) | 297 function WorldPlanPOIMixin:SetAnchor(frame, mapID, mapWidth, mapHeight) |
298 qprint(' |cFF00FF00'..self:GetName()..':SetAnchor()|r', self.questID, mapID, mapWidth) | |
136 self:ClearAllPoints() | 299 self:ClearAllPoints() |
137 local dX, dY = TQ_GetQuestLocation(self.questID, mapID) | 300 local dX, dY = TQ_GetQuestLocation(self.questID) |
138 if not dX or dX == 0 then | 301 if not dX or dX == 0 then |
139 local _, x, y = QuestPOIGetIconInfo(self.questID) | 302 local _, x, y = QuestPOIGetIconInfo(self.questID) |
140 if x and floor(x) ~= 0 then | 303 if x and floor(x) ~= 0 then |
141 dX, dY = x, y | 304 dX, dY = x, y |
142 else | 305 else |
144 end | 307 end |
145 end | 308 end |
146 self.x = dX | 309 self.x = dX |
147 self.y = dY | 310 self.y = dY |
148 | 311 |
149 qprint(' |cFF00FF00'..self.questID..':|r', format("%0.2f %0.2f", dX, dY)) | 312 --qprint(' |cFF00FF00'..self.questID..':|r', format("%0.2f %0.2f", dX, dY)) |
150 | 313 |
151 local pX = (dX * mapWidth) | 314 local pX = (dX * mapWidth) |
152 local pY = (-dY * mapHeight) | 315 local pY = (-dY * mapHeight) |
153 | 316 |
154 self:SetParent(WorldMapPOIFrame) | 317 self:SetParent(WorldMapPOIFrame) |
185 end | 348 end |
186 | 349 |
187 -- query for reward data if it wasn't found in the original scan | 350 -- query for reward data if it wasn't found in the original scan |
188 local questID = self.questID | 351 local questID = self.questID |
189 if self.isPending then | 352 if self.isPending then |
190 self:Reset() | 353 self:RefreshData() |
191 if not (self.PendingFade:IsPlaying() or self.isAnimating) then | 354 if not (self.PendingFade:IsPlaying() or self.isAnimating) then |
192 self.PendingFade:Play() | 355 self.PendingFade:Play() |
193 end | 356 end |
194 return | 357 return |
195 else | 358 else |
205 | 368 |
206 -- update time elements | 369 -- update time elements |
207 local tl = self.timeThreschold | 370 local tl = self.timeThreschold |
208 local timeLeft = TQ_GetQuestTimeLeftMinutes(questID) | 371 local timeLeft = TQ_GetQuestTimeLeftMinutes(questID) |
209 if timeLeft > 0 then | 372 if timeLeft > 0 then |
210 for i, context in ipairs(PIN_TIME_CONTEXT) do | 373 local text, timeState = WorldPlan:GetTimeInfo(timeLeft, self.TimeleftStage) |
211 if i > self.TimeleftStage then | 374 if tl ~= timeState then |
212 self.timeLabel:SetText(nil) | 375 tl = timeState |
213 break | 376 self.timeLabel:SetText(text) |
214 end | |
215 | |
216 | |
217 if timeLeft <= context.max then | |
218 if tl ~= i then | |
219 tl = i | |
220 end | |
221 | |
222 if context.format then | |
223 self.timeLabel:SetText(context.format(timeLeft)) | |
224 else | |
225 self.timeLabel:SetText(nil) | |
226 end | |
227 break | |
228 end | |
229 end | 377 end |
230 else | 378 else |
231 -- remove self in a timely manner | 379 -- remove self in a timely manner |
232 if not TQ_IsActive(self.questID) then | 380 if not TQ_IsActive(self.questID) then |
233 print('|cFFFF4400'..self:GetName()..' pin hard timeout') | 381 print('|cFFFF4400'..self:GetName()..' pin hard timeout') |
253 print('|cFF00FF88["'..tostring(self.title)..'"]|r:Refresh()', tostring(self.title), "|T"..tostring(self.itemTexture)..":12:12|t", tostring(self.itemName)) | 401 print('|cFF00FF88["'..tostring(self.title)..'"]|r:Refresh()', tostring(self.title), "|T"..tostring(self.itemTexture)..":12:12|t", tostring(self.itemName)) |
254 print(self.style) | 402 print(self.style) |
255 | 403 |
256 | 404 |
257 | 405 |
258 local questID = self.questId | 406 local questID = self:GetID() |
259 local style = self.style | 407 local style,subStyle = WorldPlan:GetTypeInfo(self.rewardType or ((self.quality or 0) + 127)) |
260 local subStyle = style[(self.filtered and 'minimized' or 'continent')] | 408 if self.filtered then |
409 subStyle = style.minimized | |
410 end | |
411 | |
261 local borderMask = style.mask | 412 local borderMask = style.mask |
262 local borderFill = style.texture | 413 local borderFill = style.texture |
263 local iconBorder = self.iconBorder | 414 local iconBorder = self.iconBorder |
264 local icon = self.icon | 415 local icon = self.icon |
265 local count = self.count | 416 local count = self.count |
278 | 429 |
279 if self.itemName then | 430 if self.itemName then |
280 local color = self.rewardColor or COMMON_COLOR | 431 local color = self.rewardColor or COMMON_COLOR |
281 | 432 |
282 | 433 |
283 self.label:SetShown( self.showNumber) | 434 |
284 if self.hasNumeric then | 435 if self.hasNumeric then |
285 self.label:SetText(self.itemNumber) | 436 self.count:SetShown(true) |
286 self.label:SetTextColor(unpack(self.numberRGB)) | 437 self.count:SetText(self.itemNumber) |
438 self.count:SetTextColor(unpack(self.numberRGB)) | |
287 else | 439 else |
288 self.label:SetText(nil) | 440 self.count:SetShown(false) |
441 self.count:SetText(nil) | |
289 end | 442 end |
290 | 443 |
291 end | 444 end |
292 | 445 |
293 SetMaskedTexture(iconBorder, borderFill, borderMask) | 446 SetMaskedTexture(iconBorder, borderFill, borderMask) |
294 local border = (self.rewardType and db.rewardStyle[self.rewardType]) or (WORLD_QUEST_QUALITY_COLORS[self.rarity] or db.defaultStyle) | 447 local border = WorldPlan:GetTypeInfo(self.rewardType) |
448 print(self.rewardType, print) | |
295 iconBorder:SetVertexColor(border.r, border.g, border.b, border.a) | 449 iconBorder:SetVertexColor(border.r, border.g, border.b, border.a) |
296 iconBorder:SetDesaturated(true) | 450 iconBorder:SetDesaturated(true) |
297 | 451 |
298 local trackingBorder = self.supertrackBorder | 452 local trackingBorder = self.supertrackBorder |
299 | 453 |
312 self.tagIcon:SetAtlas(self.tagAtlas) | 466 self.tagIcon:SetAtlas(self.tagAtlas) |
313 self.tagIcon:SetTexCoord(0,1,0,1) | 467 self.tagIcon:SetTexCoord(0,1,0,1) |
314 | 468 |
315 | 469 |
316 if self.isElite then | 470 if self.isElite then |
317 self.EliteDecal:Show() | 471 self.EliteBorder:Show() |
318 else | 472 else |
319 self.EliteDecal:Hide() | 473 self.EliteBorder:Hide() |
320 end | 474 end |
321 qprint('|cFF88FF00updated', questID, self.title, self.rewardType, (style.showNumber and self.itemNumber) or '') | 475 qprint('|cFF88FF00updated', questID, self.title, self.rewardType, (style.showNumber and self.itemNumber) or '') |
322 | 476 |
323 | 477 |
324 self:UpdateSize() | 478 self:UpdateSize() |