· 5 years ago · Oct 15, 2020, 09:10 PM
1local MogIt,mog = ...;
2_G["MogIt"] = mog;
3local L = mog.L;
4
5local ItemInfo = LibStub("LibItemInfo-1.0");
6
7LibStub("Libra"):Embed(mog);
8
9mog.frame = CreateFrame("Frame","MogItFrame",UIParent,"ButtonFrameTemplate");
10mog.list = {};
11
12function mog:Error(msg)
13 DEFAULT_CHAT_FRAME:AddMessage("MogIt: "..msg,0.9,0.5,0.9);
14end
15
16--// Slash Commands
17function mog:ToggleFrame()
18 ToggleFrame(mog.frame);
19end
20
21function mog:TogglePreview()
22 ToggleFrame(mog.view);
23end
24--//
25
26
27--// Bindings
28SLASH_MOGIT1 = "/mog";
29SLASH_MOGIT2 = "/mogit";
30SlashCmdList["MOGIT"] = mog.ToggleFrame;
31
32BINDING_HEADER_MogIt = "MogIt";
33BINDING_NAME_MogIt = L["Toggle Mogit"];
34BINDING_NAME_MogItPreview = L["Toggle Preview"];
35--//
36
37
38--// LibDataBroker
39mog.LDBI = LibStub("LibDBIcon-1.0");
40mog.mmb = LibStub("LibDataBroker-1.1"):NewDataObject("MogIt",{
41 type = "launcher",
42 icon = "Interface\\Icons\\INV_Enchant_EssenceCosmicGreater",
43 OnClick = function(self,btn)
44 if btn == "RightButton" then
45 mog:TogglePreview();
46 else
47 mog:ToggleFrame();
48 end
49 end,
50 OnTooltipShow = function(self)
51 if not self or not self.AddLine then return end
52 self:AddLine("MogIt");
53 self:AddLine(L["Left click to toggle MogIt"],1,1,1);
54 self:AddLine(L["Right click to toggle the preview"],1,1,1);
55 end,
56});
57--//
58
59
60--// Module API
61mog.moduleVersion = 3;
62mog.modules = {};
63mog.moduleList = {};
64
65function mog:GetModule(name)
66 return mog.modules[name];
67end
68
69function mog:GetActiveModule()
70 return mog.active;
71end
72
73function mog:RegisterModule(name,version,data)
74 if mog.modules[name] then
75 --mog:Error(L["The \124cFFFFFFFF%s\124r module is already loaded."]:format(name));
76 return mog.modules[name];
77 --elseif type(version) ~= "number" or version < mog.moduleVersion then
78 --mog:Error(L["The \124cFFFFFFFF%s\124r module needs to be updated to work with this version of MogIt."]:format(name));
79 --return;
80 --elseif version > mog.moduleVersion then
81 --mog:Error(L["The \124cFFFFFFFF%s\124r module requires you to update MogIt for it to work."]:format(name));
82 --return;
83 end
84 data = data or {};
85 data.version = version;
86 data.name = name;
87 mog.modules[name] = data;
88 table.insert(mog.moduleList,data);
89 if mog.menu.active == mog.menu.modules then
90 mog.menu:Rebuild(1);
91 end
92 return data;
93end
94
95function mog:SetModule(module,text)
96 if mog.active and mog.active ~= module and mog.active.Unlist then
97 mog.active:Unlist(module);
98 end
99 mog.active = module;
100 mog:BuildList(true);
101 mog:FilterUpdate();
102 mog.frame.path:SetText(text or module.label or module.name or "");
103end
104
105function mog:BuildList(top,module)
106 if (module and mog.active and mog.active.name ~= module) then return end;
107 mog.list = mog.active and mog.active.BuildList and mog.active:BuildList() or {};
108 mog:SortList(nil,true);
109 mog:UpdateScroll(top and 1);
110 mog.filt.models:SetText(#mog.list);
111end
112--//
113
114
115--// Item Cache
116local itemCacheCallbacks = {
117 BuildList = mog.BuildList;
118 ModelOnEnter = function()
119 local owner = GameTooltip:GetOwner();
120 if owner and GameTooltip[mog] then
121 owner:OnEnter();
122 end
123 end,
124 ItemMenu = function()
125 mog.Item_Menu:Rebuild(1);
126 end,
127 SetMenu = function()
128 mog.Set_Menu:Rebuild(1);
129 end,
130};
131
132local pendingCallbacks = {};
133
134for k in pairs(itemCacheCallbacks) do
135 pendingCallbacks[k] = {};
136end
137
138function mog:AddItemCacheCallback(name, func)
139 itemCacheCallbacks[name] = func;
140 pendingCallbacks[name] = {};
141end
142
143function mog:GetItemInfo(id, callback)
144 if not callback then return ItemInfo[id] end
145 if ItemInfo[id] then
146 -- clear pending items when they are cached
147 pendingCallbacks[callback][id] = nil;
148 return ItemInfo[id];
149 elseif itemCacheCallbacks[callback] then
150 -- add to pending items for this callback if not cached
151 pendingCallbacks[callback][id] = true;
152 end
153end
154
155function mog.ItemInfoReceived()
156 for k, callback in pairs(pendingCallbacks) do
157 -- execute the callback if any items are pending for it
158 if next(callback) then
159 itemCacheCallbacks[k]();
160 end
161 end
162end
163
164ItemInfo.RegisterCallback(mog, "OnItemInfoReceivedBatch", "ItemInfoReceived");
165--//
166
167local sourceItemLink = {}
168
169function mog:GetItemLinkFromSource(source)
170 if not sourceItemLink[source] then
171 local _, _, _, _, _, link = C_TransmogCollection.GetAppearanceSourceInfo(source)
172 sourceItemLink[source] = link
173 end
174 return sourceItemLink[source]
175end
176
177local itemSourceID = {}
178
179local model = CreateFrame("DressUpModel")
180model:SetAutoDress(false)
181
182function mog:GetSourceFromItem(item)
183 if not itemSourceID[item] then
184 local visualID, sourceID = C_TransmogCollection.GetItemInfo(item)
185 itemSourceID[item] = sourceID
186 if not itemSourceID[item] then
187 model:SetUnit("player")
188 model:Undress()
189 model:TryOn(item)
190 for i = 1, 19 do
191 local source = model:GetSlotTransmogSources(i)
192 if source ~= 0 then
193 itemSourceID[item] = source
194 break
195 end
196 end
197 end
198 end
199 return itemSourceID[item]
200end
201
202function mog:HasItem(sourceID, includeAlternate)
203 if not sourceID then return end
204 local found = false;
205 local sourceInfo = C_TransmogCollection.GetSourceInfo(sourceID)
206 if not sourceInfo then return end
207 found = sourceInfo.isCollected
208 if includeAlternate then
209 local _, _, _, _, _, itemClassID, itemSubclassID = GetItemInfoInstant(sourceInfo.itemID);
210 local sources = C_TransmogCollection.GetAllAppearanceSources(sourceInfo.visualID)
211 for i, sourceID in ipairs(sources) do
212 local sourceInfo = C_TransmogCollection.GetSourceInfo(sourceID)
213 local _, _, _, _, _, itemClassID2, itemSubclassID2 = GetItemInfoInstant(sourceInfo.itemID);
214 if itemSubclassID2 == itemSubclassID and sourceInfo.isCollected then
215 found = true
216 break
217 end
218 end
219 end
220 return found
221end
222
223
224--// Events
225local defaults = {
226 profile = {
227 tooltipItemID = false,
228 alwaysShowCollected = true,
229 tooltipAlwaysShowOwned = true,
230 wishlistCheckAlts = true,
231 tooltipWishlistDetail = true,
232 loadModulesDefault = false,
233
234 noAnim = false,
235 url = "Battle.net",
236
237 dressupPreview = false,
238 singlePreview = false,
239 previewUIPanel = false,
240 previewFixedSize = false,
241 previewConfirmClose = true,
242
243 sortWishlist = false,
244 loadModulesWishlist = false,
245
246 tooltip = true,
247 tooltipWidth = 300,
248 tooltipHeight = 300,
249 tooltipMouse = false,
250 tooltipDress = false,
251 tooltipRotate = true,
252 tooltipMog = true,
253 tooltipMod = "None",
254 tooltipCustomModel = false,
255 tooltipRace = 1,
256 tooltipGender = 0,
257 tooltipAnchor = "vertical",
258
259 minimap = {},
260
261 point = "CENTER",
262 gridWidth = 600,
263 gridHeight = 400,
264 rows = 2;
265 columns = 3,
266 gridDress = "preview",
267 sync = true,
268 previewProps = {
269 ["*"] = {
270 w = 335,
271 h = 385,
272 point = "CENTER",
273 }
274 },
275
276 slotLabels = {},
277 }
278}
279
280function mog.LoadSettings()
281 mog:UpdateGUI();
282
283 if mog.db.profile.minimap.hide then
284 mog.LDBI:Hide("MogIt");
285 else
286 mog.LDBI:Show("MogIt");
287 end
288
289 mog.tooltip:SetSize(mog.db.profile.tooltipWidth, mog.db.profile.tooltipHeight);
290 mog.tooltip.rotate:SetShown(mog.db.profile.tooltipRotate);
291
292 mog:UpdateScroll();
293
294 mog:SetSinglePreview(mog.db.profile.singlePreview);
295end
296
297function mog:LoadBaseModules()
298 for i, module in ipairs(self.baseModules) do
299 if GetAddOnEnableState(myName, module) > 0 and not IsAddOnLoaded(module) then
300 LoadAddOn(module)
301 end
302 end
303end
304
305mog.frame:RegisterEvent("ADDON_LOADED");
306mog.frame:RegisterEvent("PLAYER_LOGIN");
307mog.frame:RegisterEvent("GET_ITEM_INFO_RECEIVED");
308mog.frame:RegisterEvent("PLAYER_EQUIPMENT_CHANGED");
309mog.frame:RegisterEvent("TRANSMOG_SEARCH_UPDATED");
310mog.frame:SetScript("OnEvent", function(self, event, ...)
311 return mog[event] and mog[event](mog, ...)
312end);
313
314function mog:ADDON_LOADED(addon)
315 if addon == MogIt then
316 local AceDB = LibStub("AceDB-3.0")
317 mog.db = AceDB:New("MogItDB", defaults, true)
318 mog.db.RegisterCallback(mog, "OnProfileChanged", "LoadSettings")
319 mog.db.RegisterCallback(mog, "OnProfileCopied", "LoadSettings")
320 mog.db.RegisterCallback(mog, "OnProfileReset", "LoadSettings")
321
322 if not mog.db.global.version then
323 mog:Error(L["MogIt has loaded! Type \"/mog\" to open it."]);
324 end
325 mog.db.global.version = GetAddOnMetadata(MogIt,"Version");
326
327 mog.LDBI:Register("MogIt",mog.mmb,mog.db.profile.minimap);
328
329
330 for name,module in pairs(mog.moduleList) do
331 if module.MogItLoaded then
332 module:MogItLoaded()
333 end
334 end
335
336 C_TransmogCollection.SetShowMissingSourceInItemTooltips(mog.db.profile.alwaysShowCollected)
337
338 if mog.db.profile.loadModulesDefault then
339 mog:LoadBaseModules()
340 end
341 elseif mog.modules[addon] then
342 mog:LoadDB(addon)
343 mog.modules[addon].loaded = true;
344 if mog.menu.active == mog.menu.modules then
345 mog.menu:Rebuild(1)
346 end
347 elseif addon == "Blizzard_Collections" then
348 for i, model in ipairs(WardrobeCollectionFrame.ItemsCollectionFrame.Models) do
349 model:SetScript("OnMouseDown", function(self, button)
350 if IsControlKeyDown() and button == "RightButton" then
351 local link
352 local sources = WardrobeCollectionFrame_GetSortedAppearanceSources(self.visualInfo.visualID)
353 if WardrobeCollectionFrame.tooltipSourceIndex then
354 local index = WardrobeUtils_GetValidIndexForNumSources(WardrobeCollectionFrame.tooltipSourceIndex, #sources)
355 link = select(6, C_TransmogCollection.GetAppearanceSourceInfo(sources[index].sourceID))
356 end
357 mog:AddToPreview(link)
358 return
359 end
360 self:OnMouseDown(button)
361 end)
362 end
363 local orig_OnMouseUp = WardrobeCollectionFrame.SetsCollectionFrame.ScrollFrame.buttons[1]:GetScript("OnMouseUp")
364 for i, button in ipairs(WardrobeCollectionFrame.SetsCollectionFrame.ScrollFrame.buttons) do
365 button:SetScript("OnMouseUp", function(self, button)
366 if IsControlKeyDown() and button == "RightButton" then
367 local preview = mog:GetPreview()
368 for source in pairs(C_TransmogSets.GetSetSources(self.setID)) do
369 mog:AddToPreview(select(6, C_TransmogCollection.GetAppearanceSourceInfo(source)), preview)
370 end
371 return
372 end
373 orig_OnMouseUp(self, button)
374 end)
375 end
376 -- WardrobeCollectionFrame.SetsCollectionFrame.DetailsFrame.itemFramesPool.resetterFunc = function(self, obj) obj:RegisterForDrag("LeftButton", "RightButton") end
377 end
378end
379
380local str = ""
381for k, v in pairs(_G.Enum.TransmogCollectionType) do
382 str = str .. ", " .. k
383end
384
385local SLOTS = {
386 [_G.Enum.TransmogCollectionType.Head+1] = "Head",
387 [_G.Enum.TransmogCollectionType.Shoulder+1] = "Shoulder",
388 [_G.Enum.TransmogCollectionType.Back+1] = "Back",
389 [_G.Enum.TransmogCollectionType.Chest+1] = "Chest",
390 [_G.Enum.TransmogCollectionType.Shirt+1] = "Shirt",
391 [_G.Enum.TransmogCollectionType.Tabard+1] = "Tabard",
392 [_G.Enum.TransmogCollectionType.Wrist+1] = "Wrist",
393 [_G.Enum.TransmogCollectionType.Hands+1] = "Hands",
394 [_G.Enum.TransmogCollectionType.Waist+1] = "Waist",
395 [_G.Enum.TransmogCollectionType.Legs+1] = "Legs",
396 [_G.Enum.TransmogCollectionType.Feet+1] = "Feet",
397 [_G.Enum.TransmogCollectionType.Wand+1] = "Wand",
398 [_G.Enum.TransmogCollectionType.OneHAxe+1] = "1H-axe",
399 [_G.Enum.TransmogCollectionType.OneHSword+1] = "1H-sword",
400 [_G.Enum.TransmogCollectionType.OneHMace+1] = "1H-mace",
401 [_G.Enum.TransmogCollectionType.Dagger+1] = "Dagger",
402 [_G.Enum.TransmogCollectionType.Fist+1] = "Fist",
403 [_G.Enum.TransmogCollectionType.Shield+1] = "Shield",
404 [_G.Enum.TransmogCollectionType.Holdable+1] = "Holdable",
405 [_G.Enum.TransmogCollectionType.TwoHAxe+1] = "2H-axe",
406 [_G.Enum.TransmogCollectionType.TwoHSword+1] = "2H-sword",
407 [_G.Enum.TransmogCollectionType.TwoHMace+1] = "2H-mace",
408 [_G.Enum.TransmogCollectionType.Staff+1] = "Staff",
409 [_G.Enum.TransmogCollectionType.Polearm+1] = "Polearm",
410 [_G.Enum.TransmogCollectionType.Bow+1] = "Bow",
411 [_G.Enum.TransmogCollectionType.Gun+1] = "Gun",
412 [_G.Enum.TransmogCollectionType.Crossbow+1] = "Crossbow",
413 [_G.Enum.TransmogCollectionType.Warglaives+1] = "Warglaives",
414 [_G.Enum.TransmogCollectionType.Paired+1] = "ArtifactLegion",
415}
416
417local SLOT_MODULES = {
418 [_G.Enum.TransmogCollectionType.Back+1] = "Other",
419 [_G.Enum.TransmogCollectionType.Shirt+1] = "Other",
420 [_G.Enum.TransmogCollectionType.Tabard+1] = "Other",
421 [_G.Enum.TransmogCollectionType.Wand+1] = "Ranged",
422 [_G.Enum.TransmogCollectionType.OneHAxe+1] = "OneHanded",
423 [_G.Enum.TransmogCollectionType.OneHSword+1] = "OneHanded",
424 [_G.Enum.TransmogCollectionType.OneHMace+1] = "OneHanded",
425 [_G.Enum.TransmogCollectionType.Dagger+1] = "OneHanded",
426 [_G.Enum.TransmogCollectionType.Fist+1] = "OneHanded",
427 [_G.Enum.TransmogCollectionType.Shield+1] = "Other",
428 [_G.Enum.TransmogCollectionType.Holdable+1] = "Other",
429 [_G.Enum.TransmogCollectionType.TwoHAxe+1] = "TwoHanded",
430 [_G.Enum.TransmogCollectionType.TwoHSword+1] = "TwoHanded",
431 [_G.Enum.TransmogCollectionType.TwoHMace+1] = "TwoHanded",
432 [_G.Enum.TransmogCollectionType.Staff+1] = "TwoHanded",
433 [_G.Enum.TransmogCollectionType.Polearm+1] = "TwoHanded",
434 [_G.Enum.TransmogCollectionType.Bow+1] = "Ranged",
435 [_G.Enum.TransmogCollectionType.Gun+1] = "Ranged",
436 [_G.Enum.TransmogCollectionType.Crossbow+1] = "Ranged",
437 [_G.Enum.TransmogCollectionType.Warglaives+1] = "OneHanded",
438 [_G.Enum.TransmogCollectionType.Paired+1] = "Artifact",
439}
440
441mog.relevantCategories = {}
442
443function mog:TRANSMOG_SEARCH_UPDATED()
444 -- local t = debugprofilestop()
445
446 local ARMOR_CLASSES = {
447 WARRIOR = "Plate",
448 DEATHKNIGHT = "Plate",
449 PALADIN = "Plate",
450 MONK = "Leather",
451 PRIEST = "Cloth",
452 SHAMAN = "Mail",
453 DRUID = "Leather",
454 ROGUE = "Leather",
455 MAGE = "Cloth",
456 WARLOCK = "Cloth",
457 HUNTER = "Mail",
458 DEMONHUNTER = "Leather",
459 }
460
461 local FACTIONS = {
462 ["Alliance"] = 1,
463 ["Horde"] = 2,
464 -- hack for neutral pandaren, the items they can see are for both factions
465 ["Neutral"] = 3,
466 }
467
468 local _, playerClass = UnitClass("player")
469 local faction = UnitFactionGroup("player")
470
471 local armorClass = ARMOR_CLASSES[playerClass]
472
473 mog.relevantCategories[armorClass] = true
474
475 LoadAddOn("MogIt_"..armorClass)
476 LoadAddOn("MogIt_Other")
477 LoadAddOn("MogIt_OneHanded")
478 LoadAddOn("MogIt_TwoHanded")
479 LoadAddOn("MogIt_Ranged")
480 LoadAddOn("MogIt_Artifact")
481
482 local ArmorDB = _G["MogIt_"..armorClass.."DB"] or {}
483 MogIt_OtherDB = MogIt_OtherDB or {}
484 MogIt_OneHandedDB = MogIt_OneHandedDB or {}
485 MogIt_TwoHandedDB = MogIt_TwoHandedDB or {}
486 MogIt_RangedDB = MogIt_RangedDB or {}
487 MogIt_ArtifactDB = MogIt_ArtifactDB or {}
488
489 _G["MogIt_"..armorClass.."DB"] = ArmorDB
490
491 local GetAppearanceSources = C_TransmogCollection.GetAppearanceSources
492 local GetAppearanceSourceDrops = C_TransmogCollection.GetAppearanceSourceDrops
493 local bor = bit.bor
494
495 for i = 1, _G.Enum.TransmogCollectionTypeMeta.NumValues do
496 local name, isWeapon, canEnchant, canMainHand, canOffHand = C_TransmogCollection.GetCategoryInfo(i)
497 if name then
498 name = SLOTS[i]
499 local db = db
500 if isWeapon then
501 mog.relevantCategories[name] = true
502 end
503 if SLOT_MODULES[i] then
504 db = _G["MogIt_"..SLOT_MODULES[i].."DB"]
505 else
506 db = ArmorDB
507 end
508 db[name] = db[name] or {}
509 -- required to include all artifacts
510 local exclusionCategory
511 if canMainHand then
512 exclusionCategory = 2
513 end
514 for i, appearance in ipairs(C_TransmogCollection.GetCategoryAppearances(i, exclusionCategory)) do
515 if not appearance.isHideVisual then
516 local v = db[name][appearance.visualID] or {}
517 db[name][appearance.visualID] = v
518 if v[1] and v[1].sourceID then
519 db[name][appearance.visualID] = {}
520 end
521 for i, source in ipairs(GetAppearanceSources(appearance.visualID)) do
522 local s = v[source.sourceID] or {}
523 v[source.sourceID] = s
524 s.sourceType = source.sourceType
525 s.drops = GetAppearanceSourceDrops(source.sourceID)
526 s.classes = bor(s.classes or 0, L.classBits[playerClass])
527 s.faction = bor(s.faction or 0, FACTIONS[faction])
528 end
529 end
530 end
531 end
532 end
533
534 self:LoadDB("MogIt_"..armorClass)
535 self:LoadDB("MogIt_Other")
536 self:LoadDB("MogIt_OneHanded")
537 self:LoadDB("MogIt_TwoHanded")
538 self:LoadDB("MogIt_Ranged")
539 self:LoadDB("MogIt_Artifact")
540
541 self.frame:UnregisterEvent("TRANSMOG_SEARCH_UPDATED")
542
543 -- print(format("MogIt modules loaded in %d ms.", debugprofilestop() - t))
544end
545
546function mog:LoadDB(addon)
547 if not IsAddOnLoaded(addon) then return end
548 local SOURCE_TYPES = {
549 [1] = 1,
550 [2] = 3,
551 [3] = 4,
552 [4] = 1,
553 [5] = 6,
554 [6] = 5,
555 }
556
557 local module = mog:GetModule(addon)
558 local moduleDB = _G[addon.."DB"]
559
560 -- won't exist if module was never loaded
561 if not moduleDB then return end
562
563 for slot, appearances in pairs(moduleDB) do
564 local list = {}
565 module.slots[slot] = {
566 label = slot,
567 list = list,
568 }
569 wipe(module.slotList)
570 for visualID, appearance in pairs(appearances) do
571 for sourceID, source in pairs(appearance) do
572 local id = source.sourceID or sourceID
573 tinsert(list, id)
574 mog:AddData("item", id, "display", visualID)
575 -- mog:AddData("item", id, "level", lvl)
576 mog:AddData("item", id, "faction", source.faction)
577 mog:AddData("item", id, "class", source.classes)
578 mog:AddData("item", id, "source", SOURCE_TYPES[source.sourceType])
579 -- mog:AddData("item", id, "sourceid", sourceid)
580 mog:AddData("item", id, "sourceinfo", source.drops)
581 -- mog:AddData("item", id, "zone", zone)
582 end
583 end
584 end
585
586 for i = 1, _G.Enum.TransmogCollectionTypeMeta.NumValues do
587 local slotID = SLOTS[i]
588 if moduleDB[slotID] then
589 tinsert(module.slotList, slotID)
590 end
591 end
592end
593
594
595function mog:TRANSMOG_COLLECTION_SOURCE_ADDED(sourceID)
596end
597
598
599function mog:PLAYER_LOGIN()
600 C_Timer.After(1, function()
601 --this function doesn't yield correct results immediately, so we delay it
602 for slot, v in pairs(mog.mogSlots) do
603 local transmogLocation = TransmogUtil.GetTransmogLocation(slot, Enum.TransmogType.Appearance, Enum.TransmogModification.None)
604 local isTransmogrified, _, _, _, _, _, _, visibleItemID = C_Transmog.GetSlotInfo(transmogLocation);
605 if isTransmogrified then
606 -- we need an item ID here if we still need to cache these at all
607 -- mog:GetItemInfo(visibleItemID);
608 end
609 end
610 end)
611
612 for k, slot in pairs(SLOTS) do
613 local name = C_TransmogCollection.GetCategoryInfo(k)
614 if name then
615 mog.db.profile.slotLabels[slot] = name
616 end
617 end
618
619 mog:LoadSettings();
620 self.frame:SetScript("OnSizeChanged", function(self, width, height)
621 mog.db.profile.gridWidth = width;
622 mog.db.profile.gridHeight = height;
623 mog:UpdateGUI(true);
624 end)
625end
626
627
628function mog:PLAYER_EQUIPMENT_CHANGED(slot, hasItem)
629 local slotName = mog.mogSlots[slot];
630 local item = GetInventoryItemLink("player", slot);
631 if slotName then
632 local transmogLocation = TransmogUtil.GetTransmogLocation(slot, Enum.TransmogType.Appearance, Enum.TransmogModification.None)
633 local baseSourceID, baseVisualID, appliedSourceID, appliedVisualID = C_Transmog.GetSlotVisualInfo(transmogLocation);
634 local isTransmogrified, _, _, _, _, _, isHideVisual, texture = C_Transmog.GetSlotInfo(transmogLocation);
635 if isTransmogrified then
636 -- we need an item ID here if we still need to cache these at all
637 -- mog:GetItemInfo(visibleItemID);
638 item = appliedSourceID;
639 itemAppearanceModID = visibleItemAppearanceModID;
640 end
641 end
642 -- don't do anything if the slot is not visible (necklace, ring, trinket)
643 if mog.db.profile.gridDress == "equipped" then
644 for i, frame in ipairs(mog.models) do
645 if frame.data.item then
646 if hasItem then
647 frame:TryOn(item, slotName, itemAppearanceModID);
648 else
649 frame:UndressSlot(slot);
650 end
651 frame:TryOn(frame.data.item);
652 end
653 end
654 end
655end
656--//
657
658
659--// Data API
660mog.data = {};
661
662function mog:AddData(data, id, key, value)
663 if not (data and id and key) then return end;
664
665 --if data == "item" then
666 -- id = mog:ItemToString(id);
667 --end
668
669 if not mog.data[data] then
670 mog.data[data] = {};
671 end
672 if not mog.data[data][key] then
673 mog.data[data][key] = {};
674 end
675 mog.data[data][key][id] = value;
676 return value;
677end
678
679function mog:DeleteData(data, id, key)
680 if not mog.data[data] then return end;
681 if id and key then
682 mog.data[data][key][id] = nil;
683 elseif id then
684 for k,v in pairs(mog.data[data]) do
685 v[id] = nil;
686 end
687 elseif key then
688 mog.data[data][key] = nil;
689 else
690 mog.data[data] = nil;
691 end
692end
693
694function mog:GetData(data, id, key)
695 return mog.data[data] and mog.data[data][key] and mog.data[data][key][id];
696end
697
698mog.itemStringShort = "item:%d:0";
699mog.itemStringLong = "item:%d:0::::::::::%d:1:%d";
700
701function mog:ToStringItem(id, bonus, diff)
702 -- itemID, enchantID, instanceDifficulty, numBonusIDs, bonusID1
703 if (bonus and bonus ~= 0) or (diff and diff ~= 0) then
704 return format(mog.itemStringLong, id, diff or 0, bonus or 0);
705 else
706 return format(mog.itemStringShort, id);
707 end
708end
709
710local bonusDiffs = {
711 -- MoP
712 [451] = true, -- Raid Finder
713 [449] = true, -- Heroic (Raid)
714 [450] = true, -- Mythic (Raid)
715 -- WoD
716 [518] = true, -- dungeon-level-up-1
717 [519] = true, -- dungeon-level-up-2
718 [520] = true, -- dungeon-level-up-3
719 [521] = true, -- dungeon-level-up-4
720 [522] = true, -- dungeon-normal
721 [524] = true, -- dungeon-heroic
722 [525] = true, -- trade-skill (tier 1)
723 [526] = true, -- trade-skill (armor tier 2)
724 [527] = true, -- trade-skill (armor tier 3)
725 [558] = true, -- trade-skill (weapon tier 2)
726 [559] = true, -- trade-skill (weapon tier 3)
727 [566] = true, -- raid-heroic
728 [567] = true, -- raid-mythic
729 [593] = true, -- trade-skill (armor tier 4)
730 [594] = true, -- trade-skill (weapon tier 4)
731 [615] = true, -- timewalker
732 [617] = true, -- trade-skill (armor tier 5)
733 [618] = true, -- trade-skill (armor tier 6)
734 [619] = true, -- trade-skill (weapon tier 5)
735 [620] = true, -- trade-skill (weapon tier 6)
736 [642] = true, -- dungeon-mythic
737 [648] = true, -- baleful (675)
738 [651] = true, -- baleful empowered (695)
739 [1798] = true, -- ???
740 [1799] = true, -- ???
741 [1805] = true, -- raid-heroic
742 [1806] = true, -- raid-mythic
743 [3379] = true, -- ???
744 [3444] = true, -- ???
745 [3445] = true, -- ???
746 [3446] = true, -- ???
747
748 [3524] = true, -- magical bonus ID for items that instead use the instance difficulty ID parameter
749};
750
751mog.itemStringPattern = "item:(%d+):%d*:%d*:%d*:%d*:%d*:%d*:%d*:%d*:%d*:%d*:(%d*):%d*:([%d:]+)";
752
753function mog:ToNumberItem(item)
754 if type(item) == "string" then
755 local id, diff, bonus = item:match(mog.itemStringPattern);
756 -- bonus ID can also be warforged, socketed, etc
757 -- if there is more than one bonus ID, need to check all
758 if bonus then
759 if not tonumber(bonus) then
760 for bonusID in gmatch(bonus, "%d+") do
761 if bonusDiffs[tonumber(bonusID)] then
762 bonus = bonusID;
763 break;
764 end
765 end
766 elseif not bonusDiffs[tonumber(bonus)] then
767 bonus = nil;
768 end
769 end
770 id = id or item:match("item:(%d+)");
771 return tonumber(id), tonumber(bonus), tonumber(diff);
772 elseif type(item) == "number" then
773 return item;
774 end
775end
776
777function mog:NormaliseItemString(item)
778 return self:ToStringItem(self:ToNumberItem(item));
779end
780--//
781
782
783--// Slot Conversion
784mog.slots = {
785 "HeadSlot",
786 "ShoulderSlot",
787 "BackSlot",
788 "ChestSlot",
789 "ShirtSlot",
790 "TabardSlot",
791 "WristSlot",
792 "HandsSlot",
793 "WaistSlot",
794 "LegsSlot",
795 "FeetSlot",
796 "MainHandSlot",
797 "SecondaryHandSlot",
798};
799
800mog.slotsType = {
801 INVTYPE_HEAD = "HeadSlot",
802 INVTYPE_SHOULDER = "ShoulderSlot",
803 INVTYPE_CLOAK = "BackSlot",
804 INVTYPE_CHEST = "ChestSlot",
805 INVTYPE_ROBE = "ChestSlot",
806 INVTYPE_BODY = "ShirtSlot",
807 INVTYPE_TABARD = "TabardSlot",
808 INVTYPE_WRIST = "WristSlot",
809 INVTYPE_HAND = "HandsSlot",
810 INVTYPE_WAIST = "WaistSlot",
811 INVTYPE_LEGS = "LegsSlot",
812 INVTYPE_FEET = "FeetSlot",
813 INVTYPE_2HWEAPON = "MainHandSlot",
814 INVTYPE_WEAPON = "MainHandSlot",
815 INVTYPE_WEAPONMAINHAND = "MainHandSlot",
816 INVTYPE_WEAPONOFFHAND = "SecondaryHandSlot",
817 INVTYPE_RANGED = "MainHandSlot",
818 INVTYPE_RANGEDRIGHT = "MainHandSlot",
819 INVTYPE_SHIELD = "SecondaryHandSlot",
820 INVTYPE_HOLDABLE = "SecondaryHandSlot",
821};
822
823-- all slot IDs that can be transmogrified
824mog.mogSlots = {
825 [INVSLOT_HEAD] = "HeadSlot",
826 [INVSLOT_SHOULDER] = "ShoulderSlot",
827 [INVSLOT_BACK] = "BackSlot",
828 [INVSLOT_CHEST] = "ChestSlot",
829 [INVSLOT_BODY] = "ShirtSlot",
830 [INVSLOT_TABARD] = "TabardSlot",
831 [INVSLOT_WRIST] = "WristSlot",
832 [INVSLOT_HAND] = "HandsSlot",
833 [INVSLOT_WAIST] = "WaistSlot",
834 [INVSLOT_LEGS] = "LegsSlot",
835 [INVSLOT_FEET] = "FeetSlot",
836 [INVSLOT_MAINHAND] = "MainHandSlot",
837 [INVSLOT_OFFHAND] = "SecondaryHandSlot",
838}
839
840function mog:GetSlot(id)
841 return mog.slots[id] or mog.slotsType[id];
842end
843--//
844