Advertisement
pragma

AppearanceTooltip fix (sort of)

Jan 31st, 2019
222
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 22.65 KB | None | 0 0
  1. local myname, ns = ...
  2. local myfullname = GetAddOnMetadata(myname, "Title")
  3.  
  4. local GetScreenWidth = GetScreenWidth
  5. local GetScreenHeight = GetScreenHeight
  6. local IsDressableItem = IsDressableItem
  7.  
  8. local setDefaults, db
  9.  
  10. local LAT = LibStub("LibArmorToken-1.0")
  11. local LAI = LibStub("LibAppropriateItems-1.0")
  12.  
  13. local tooltip = CreateFrame("Frame", "AppearanceTooltipTooltip", UIParent, "TooltipBorderedFrameTemplate")
  14. tooltip:SetClampedToScreen(true)
  15. tooltip:SetFrameStrata("TOOLTIP")
  16. tooltip:SetSize(280, 380)
  17. tooltip:Hide()
  18.  
  19. tooltip:SetScript("OnEvent", function(self, event, ...)
  20.     self[event](self, ...)
  21. end)
  22. tooltip:RegisterEvent("ADDON_LOADED")
  23. tooltip:RegisterEvent("PLAYER_LOGIN")
  24. tooltip:RegisterEvent("PLAYER_REGEN_DISABLED")
  25. tooltip:RegisterEvent("PLAYER_REGEN_ENABLED")
  26.  
  27. function tooltip:ADDON_LOADED(addon)
  28.     if addon ~= myname then return end
  29.  
  30.     _G[myname.."DB"] = setDefaults(_G[myname.."DB"] or {}, {
  31.         modifier = "None", -- or "Alt", "Ctrl", "Shift"
  32.         mousescroll = true, -- scrolling mouse rotates model
  33.         rotate = true, -- turn the model slightly, so it's not face-on to the camera
  34.         spin = false, -- constantly spin the model
  35.         zoomWorn = true, -- zoom in on the item in question
  36.         zoomHeld = true, -- zoom in on weapons
  37.         zoomMasked = false, -- use the transmog mask while zoomed
  38.         dressed = true, -- whether the model should be wearing your current outfit, or be naked
  39.         uncover = true, -- remove clothing to expose the previewed item
  40.         customModel = false, -- use a model other than your current class, and if so:
  41.         modelRace = 7, -- raceid (1:human)
  42.         modelGender = 1, -- 0:male, 1:female
  43.         notifyKnown = true, -- show text explaining the transmog state of the item previewed
  44.         currentClass = false, -- only show for items the current class can transmog
  45.         anchor = "vertical", -- vertical / horizontal
  46.         byComparison = true, -- whether to show by the comparison, or fall back to vertical if needed
  47.         tokens = true, -- try to preview tokens?
  48.     })
  49.     db = _G[myname.."DB"]
  50.     ns.db = db
  51.  
  52.     self:UnregisterEvent("ADDON_LOADED")
  53. end
  54.  
  55. function tooltip:PLAYER_LOGIN()
  56.     tooltip.model:SetUnit("player")
  57.     tooltip.modelZoomed:SetUnit("player")
  58.     C_TransmogCollection.SetShowMissingSourceInItemTooltips(true)
  59. end
  60.  
  61. function tooltip:PLAYER_REGEN_ENABLED()
  62.     if self:IsShown() and db.mousescroll then
  63.         SetOverrideBinding(tooltip, true, "MOUSEWHEELUP", "AppearanceKnown_TooltipScrollUp")
  64.         SetOverrideBinding(tooltip, true, "MOUSEWHEELDOWN", "AppearanceKnown_TooltipScrollDown")
  65.     end
  66. end
  67.  
  68. function tooltip:PLAYER_REGEN_DISABLED()
  69.     ClearOverrideBindings(tooltip)
  70. end
  71.  
  72. tooltip:SetScript("OnShow", function(self)
  73.     if db.mousescroll and not InCombatLockdown() then
  74.         SetOverrideBinding(tooltip, true, "MOUSEWHEELUP", "AppearanceKnown_TooltipScrollUp")
  75.         SetOverrideBinding(tooltip, true, "MOUSEWHEELDOWN", "AppearanceKnown_TooltipScrollDown")
  76.     end
  77. end);
  78.  
  79. tooltip:SetScript("OnHide",function(self)
  80.     if not InCombatLockdown() then
  81.         ClearOverrideBindings(tooltip);
  82.     end
  83. end)
  84.  
  85. local function makeModel()
  86.     local model = CreateFrame("DressUpModel", nil, tooltip)
  87.     model:SetFrameLevel(1)
  88.     model:SetPoint("TOPLEFT", tooltip, "TOPLEFT", 5, -5)
  89.     model:SetPoint("BOTTOMRIGHT", tooltip, "BOTTOMRIGHT", -5, 5)
  90.     model:SetKeepModelOnHide(true)
  91.     model:SetScript("OnModelLoaded", function(self, ...)
  92.         -- Makes sure the zoomed camera is correct, if the model isn't loaded right away
  93.         if self.cameraID then
  94.             Model_ApplyUICamera(self, self.cameraID)
  95.         end
  96.     end)
  97.     -- Use the blacked-out model:
  98.     -- model:SetUseTransmogSkin(true)
  99.     -- Display in combat pose:
  100.     -- model:FreezeAnimation(1)
  101.     return model
  102. end
  103. tooltip.model = makeModel()
  104. tooltip.modelZoomed = makeModel()
  105. tooltip.modelWeapon = makeModel()
  106.  
  107. tooltip.model:SetScript("OnShow", function(self)
  108.     -- Initial display will be off-center without this
  109.     ns:ResetModel(self)
  110. end)
  111.  
  112. local known = tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal")
  113. known:SetWordWrap(true)
  114. known:SetTextColor(0.5333, 0.6666, 0.9999, 0.9999)
  115. known:SetPoint("BOTTOMLEFT", tooltip, "BOTTOMLEFT", 6, 12)
  116. known:SetPoint("BOTTOMRIGHT", tooltip, "BOTTOMRIGHT", -6, 12)
  117. known:Show()
  118.  
  119. local classwarning = tooltip:CreateFontString(nil, "OVERLAY", "GameFontRed")
  120. classwarning:SetWordWrap(true)
  121. classwarning:SetPoint("TOPLEFT", tooltip, "TOPLEFT", 6, -12)
  122. classwarning:SetPoint("TOPRIGHT", tooltip, "TOPRIGHT", -6, -12)
  123. -- ITEM_WRONG_CLASS = "That item can't be used by players of your class!"
  124. -- STAT_USELESS_TOOLTIP = "|cff808080Provides no benefit for your class|r"
  125. classwarning:SetText("Your class can't transmogrify this item")
  126. classwarning:Show()
  127.  
  128. -- Ye showing:
  129. GameTooltip:HookScript("OnTooltipSetItem", function(self)
  130.     ns:ShowItem(select(2, self:GetItem()))
  131. end)
  132. GameTooltip:HookScript("OnHide", function()
  133.     ns:HideItem()
  134. end)
  135.  
  136. ----
  137.  
  138. local positioner = CreateFrame("Frame")
  139. positioner:Hide()
  140. positioner:SetScript("OnShow", function(self)
  141.     -- always run immediately
  142.     self.elapsed = TOOLTIP_UPDATE_TIME
  143. end)
  144. positioner:SetScript("OnUpdate", function(self, elapsed)
  145.     self.elapsed = self.elapsed + elapsed
  146.     if self.elapsed < TOOLTIP_UPDATE_TIME then
  147.         return
  148.     end
  149.     self.elapsed = 0
  150.  
  151.     local owner, our_point, owner_point = ns:ComputeTooltipAnchors(tooltip.owner, tooltip, db.anchor)
  152.     if our_point and owner_point then
  153.         tooltip:ClearAllPoints()
  154.         tooltip:SetPoint(our_point, owner, owner_point)
  155.     end
  156. end)
  157.  
  158. do
  159.     local points = {
  160.         -- key is the direction our tooltip should be biased, with the first component being the primary (i.e. "on the top side, to the left")
  161.         -- these are [our point, owner point]
  162.         top = {
  163.             left = {"BOTTOMRIGHT", "TOPRIGHT"},
  164.             right = {"BOTTOMLEFT", "TOPLEFT"},
  165.         },
  166.         bottom = {
  167.             left = {"TOPRIGHT", "BOTTOMRIGHT"},
  168.             right = {"TOPLEFT", "BOTTOMLEFT"},
  169.         },
  170.         left = {
  171.             top = {"BOTTOMRIGHT", "BOTTOMLEFT"},
  172.             bottom = {"TOPRIGHT", "TOPLEFT"},
  173.         },
  174.         right = {
  175.             top = {"BOTTOMLEFT", "BOTTOMRIGHT"},
  176.             bottom = {"TOPLEFT", "TOPRIGHT"},
  177.         },
  178.     }
  179.     function ns:ComputeTooltipAnchors(owner, tooltip, anchor)
  180.         -- Because I always forget: x is left-right, y is bottom-top
  181.         -- Logic here: our tooltip should trend towards the center of the screen, unless something is stopping it.
  182.         -- If comparison tooltips are shown, we shouldn't overlap them
  183.         local originalOwner = owner
  184.         local x, y = owner:GetCenter()
  185.         if not (x and y) then
  186.             return
  187.         end
  188.         x = x * owner:GetEffectiveScale()
  189.         -- the y comparison doesn't need this:
  190.         -- y = y * owner:GetEffectiveScale()
  191.  
  192.         local biasLeft, biasDown
  193.         -- we want to follow the direction the tooltip is going, relative to the cursor
  194.         -- print("biasLeft check", x ,"<", GetCursorPosition())
  195.         -- print("biasDown check", y, ">", GetScreenHeight() / 2)
  196.         biasLeft = x < GetCursorPosition()
  197.         biasDown = y > GetScreenHeight() / 2
  198.  
  199.         local outermostComparisonShown
  200.         if owner.shoppingTooltips then
  201.             local comparisonTooltip1, comparisonTooltip2 = unpack( owner.shoppingTooltips )
  202.             if comparisonTooltip1:IsShown() or comparisonTooltip2:IsShown() then
  203.                 if comparisonTooltip1:IsShown() and comparisonTooltip2:IsShown() then
  204.                     if comparisonTooltip1:GetCenter() > comparisonTooltip2:GetCenter() then
  205.                         -- 1 is right of 2
  206.                         outermostComparisonShown = biasLeft and comparisonTooltip2 or comparisonTooltip1
  207.                     else
  208.                         -- 1 is left of 2
  209.                         outermostComparisonShown = biasLeft and comparisonTooltip1 or comparisonTooltip2
  210.                     end
  211.                 else
  212.                     outermostComparisonShown = comparisonTooltip1:IsShown() and comparisonTooltip1 or comparisonTooltip2
  213.                 end
  214.                 if
  215.                     -- outermost is right of owner while we're biasing left
  216.                     (biasLeft and outermostComparisonShown:GetCenter() > owner:GetCenter())
  217.                     or
  218.                     -- outermost is left of owner while we're biasing right
  219.                     ((not biasLeft) and outermostComparisonShown:GetCenter() < owner:GetCenter())
  220.                 then
  221.                     -- the comparison won't be in the way, so ignore it
  222.                     outermostComparisonShown = nil
  223.                 end
  224.             end
  225.         end
  226.  
  227.         -- print("ApTip bias", biasLeft and "left" or "right", biasDown and "down" or "up")
  228.  
  229.         local primary, secondary
  230.         if anchor == "vertical" then
  231.             -- attaching to the top/bottom of the tooltip
  232.             -- only care about comparisons to avoid overlapping them
  233.             primary = biasDown and "bottom" or "top"
  234.             if outermostComparisonShown then
  235.                 secondary = biasLeft and "right" or "left"
  236.             else
  237.                 secondary = biasLeft and "left" or "right"
  238.             end
  239.         else -- horizontal
  240.             primary = biasLeft and "left" or "right"
  241.             secondary = biasDown and "bottom" or "top"
  242.             if outermostComparisonShown then
  243.                 if db.byComparison then
  244.                     owner = outermostComparisonShown
  245.                 else
  246.                     -- show on the opposite side of the bias, probably overlapping the cursor, since that's better than overlapping the comparison
  247.                     primary = biasLeft and "right" or "left"
  248.                 end
  249.             end
  250.         end
  251.         if
  252.             -- would we be pushing against the edge of the screen?
  253.             (primary == "left" and (owner:GetLeft() - tooltip:GetWidth()) < 0)
  254.             or (primary == "right" and (owner:GetRight() + tooltip:GetWidth() > GetScreenWidth()))
  255.         then
  256.             return self:ComputeTooltipAnchors(originalOwner, tooltip, "vertical")
  257.         end
  258.         return owner, unpack(points[primary][secondary])
  259.     end
  260. end
  261.  
  262. local spinner = CreateFrame("Frame", nil, tooltip);
  263. spinner:Hide()
  264. spinner:SetScript("OnUpdate", function(self, elapsed)
  265.     if not (tooltip.activeModel and tooltip.activeModel:IsVisible()) then
  266.         return self:Hide()
  267.     end
  268.     tooltip.activeModel:SetFacing(tooltip.activeModel:GetFacing() + elapsed)
  269. end)
  270.  
  271. local hider = CreateFrame("Frame")
  272. hider:Hide()
  273. hider:SetScript("OnUpdate", function(self)
  274.     if (tooltip.owner and not (tooltip.owner:IsShown() and tooltip.owner:GetItem())) or not tooltip.owner then
  275.         spinner:Hide()
  276.         positioner:Hide()
  277.         tooltip:Hide()
  278.         tooltip.item = nil
  279.     end
  280.     self:Hide()
  281. end)
  282.  
  283. ----
  284.  
  285. local _, class = UnitClass("player")
  286.  
  287. function GetItemAppearance(itemLink)
  288.     local InventorySlots = {
  289.         ['INVTYPE_HEAD'] = 1,
  290.         ['INVTYPE_NECK'] = 2,
  291.         ['INVTYPE_SHOULDER'] = 3,
  292.         ['INVTYPE_BODY'] = 4,
  293.         ['INVTYPE_CHEST'] = 5,
  294.         ['INVTYPE_ROBE'] = 5,
  295.         ['INVTYPE_WAIST'] = 6,
  296.         ['INVTYPE_LEGS'] = 7,
  297.         ['INVTYPE_FEET'] = 8,
  298.         ['INVTYPE_WRIST'] = 9,
  299.         ['INVTYPE_HAND'] = 10,
  300.         ['INVTYPE_CLOAK'] = 15,
  301.         ['INVTYPE_WEAPON'] = 16,
  302.         ['INVTYPE_SHIELD'] = 17,
  303.         ['INVTYPE_2HWEAPON'] = 16,
  304.         ['INVTYPE_WEAPONMAINHAND'] = 16,
  305.         ['INVTYPE_RANGED'] = 16,
  306.         ['INVTYPE_RANGEDRIGHT'] = 16,
  307.         ['INVTYPE_WEAPONOFFHAND'] = 17,
  308.         ['INVTYPE_HOLDABLE'] = 17,
  309.     }
  310.     local model = CreateFrame('DressUpModel')
  311.     local itemID, _, _, slotName = GetItemInfoInstant(itemLink)
  312.     if itemLink == itemID then
  313.         itemLink = 'item:' .. itemID
  314.     end
  315.     local slot = InventorySlots[slotName]
  316.     if not slot or not IsDressableItem(itemLink) then return end
  317.     model:SetUnit('player')
  318.     model:Undress()
  319.     model:TryOn(itemLink, slot)
  320.     local sourceID = model:GetSlotTransmogSources(slot)
  321.     if sourceID then
  322.         local categoryID, appearanceID, canEnchant, texture, isCollected, itemLink = C_TransmogCollection.GetAppearanceSourceInfo(sourceID)
  323.         return appearanceID
  324.     end
  325. end
  326.  
  327. function ns:ShowItem(link)
  328.     if not link then return end
  329.     local id = tonumber(link:match("item:(%d+)"))
  330.     if not id or id == 0 then return end
  331.     local token = db.tokens and LAT:ItemIsToken(id)
  332.     local maybelink, _
  333.  
  334.     if token then
  335.         -- It's a set token! Replace the id.
  336.         local found
  337.         for _, itemid in LAT:IterateItemsForTokenAndClass(id, class) do
  338.             _, maybelink = GetItemInfo(itemid)
  339.             if maybelink then
  340.                 id = itemid
  341.                 link = maybelink
  342.                 found = true
  343.                 break
  344.             end
  345.         end
  346.         if not found then
  347.             for _, tokenclass in LAT:IterateClassesForToken(id) do
  348.                 for _, itemid in LAT:IterateItemsForTokenAndClass(id, tokenclass) do
  349.                     _, maybelink = GetItemInfo(itemid)
  350.                     if maybelink then
  351.                         id = itemid
  352.                         link = maybelink
  353.                         found = true
  354.                         break
  355.                     end
  356.                 end
  357.                 break
  358.             end
  359.         end
  360.         if found then
  361.             GameTooltip:AddDoubleLine(ITEM_PURCHASED_COLON, link)
  362.             GameTooltip:Show()
  363.         end
  364.     end
  365.  
  366.     local slot = select(9, GetItemInfo(id))
  367.     if (not db.modifier or self.modifiers[db.modifier]()) and tooltip.item ~= id then
  368.         tooltip.item = id
  369.  
  370.         local appropriateItem = LAI:IsAppropriate(id)
  371.  
  372.         if self.slot_facings[slot] and IsDressableItem(id) and (not db.currentClass or appropriateItem) then
  373.             local model
  374.             local cameraID, itemCamera
  375.             if db.zoomWorn or db.zoomHeld then
  376.                 cameraID, itemCamera = self:GetCameraID(id, db.customModel and db.modelRace, db.customModel and db.modelGender)
  377.             end
  378.  
  379.             tooltip.model:Hide()
  380.             tooltip.modelZoomed:Hide()
  381.             tooltip.modelWeapon:Hide()
  382.  
  383.             local shouldZoom = (db.zoomHeld and cameraID and itemCamera) or (db.zoomWorn and cameraID and not itemCamera)
  384.  
  385.             if shouldZoom then
  386.                 if itemCamera then
  387.                     model = tooltip.modelWeapon
  388.                     local appearanceID = GetItemAppearance(link)
  389.                     model:SetItemAppearance(appearanceID)
  390.                 else
  391.                     model = tooltip.modelZoomed
  392.                     model:SetUseTransmogSkin(db.zoomMasked and slot ~= "INVTYPE_HEAD")
  393.                     self:ResetModel(model)
  394.                 end
  395.                 model.cameraID = cameraID
  396.                 Model_ApplyUICamera(model, cameraID)
  397.                 -- ApplyUICamera locks the animation, but...
  398.                 model:SetAnimation(0, 0)
  399.             else
  400.                 model = tooltip.model
  401.  
  402.                 self:ResetModel(model)
  403.             end
  404.             tooltip.activeModel = model
  405.             model:Show()
  406.  
  407.             if not cameraID then
  408.                 model:SetFacing(self.slot_facings[slot] - (db.rotate and 0.5 or 0))
  409.             end
  410.  
  411.             tooltip:Show()
  412.             tooltip.owner = GameTooltip
  413.  
  414.             positioner:Show()
  415.             spinner:SetShown(db.spin)
  416.  
  417.             if ns.slot_removals[slot] and (ns.always_remove[slot] or db.uncover) then
  418.                 -- 1. If this is a weapon, force-remove the item in the main-hand slot! Otherwise it'll get dressed into the
  419.                 --    off-hand, maybe, depending on things which are more hassle than it's worth to work out.
  420.                 -- 2. Other slots will be entirely covered, making for a useless preview. e.g. shirts.
  421.                 for _, slotid in ipairs(ns.slot_removals[slot]) do
  422.                     if slotid == ns.SLOT_ROBE then
  423.                         local chest_itemid = GetInventoryItemID("player", ns.SLOT_CHEST)
  424.                         if chest_itemid and select(4, GetItemInfoInstant(chest_itemid)) == 'INVTYPE_ROBE' then
  425.                             slotid = ns.SLOT_CHEST
  426.                         end
  427.                     end
  428.                     if slotid > 0 then
  429.                         model:UndressSlot(slotid)
  430.                     end
  431.                 end
  432.             end
  433.             model:TryOn(link)
  434.         else
  435.             tooltip:Hide()
  436.         end
  437.  
  438.         classwarning:Hide()
  439.         known:Hide()
  440.  
  441.         if db.notifyKnown then
  442.             local hasAppearance, appearanceFromOtherItem, notTransmoggable = ns.PlayerHasAppearance(link)
  443.  
  444.             local label
  445.             if notTransmoggable then
  446.                 label = "|c00ffff00" .. TRANSMOGRIFY_INVALID_DESTINATION
  447.             else
  448.                 if hasAppearance then
  449.                     if appearanceFromOtherItem then
  450.                         label = "|TInterface\\RaidFrame\\ReadyCheck-Ready:0|t " .. (TRANSMOGRIFY_TOOLTIP_ITEM_UNKNOWN_APPEARANCE_KNOWN):gsub(', ', ',\n')
  451.                     else
  452.                         label = "|TInterface\\RaidFrame\\ReadyCheck-Ready:0|t " .. TRANSMOGRIFY_TOOLTIP_APPEARANCE_KNOWN
  453.                     end
  454.                 else
  455.                     label = "|TInterface\\RaidFrame\\ReadyCheck-NotReady:0|t |cffff0000" .. TRANSMOGRIFY_TOOLTIP_APPEARANCE_UNKNOWN
  456.                 end
  457.                 classwarning:SetShown(not appropriateItem)
  458.             end
  459.             known:SetText(label)
  460.             known:Show()
  461.         end
  462.     end
  463. end
  464.  
  465. function ns:HideItem()
  466.     hider:Show()
  467. end
  468.  
  469. function ns:ResetModel(model)
  470.     -- This sort of works, but with a custom model it keeps some items (shoulders, belt...)
  471.     -- model:SetAutoDress(db.dressed)
  472.     -- So instead, more complicated:
  473.     if db.customModel then
  474.         model:SetCustomRace(db.modelRace, db.modelGender)
  475.     else
  476.         model:Dress()
  477.     end
  478.     model:RefreshCamera()
  479.     if not db.dressed then
  480.         model:Undress()
  481.     end
  482. end
  483.  
  484. ns.SLOT_MAINHAND = GetInventorySlotInfo("MainHandSlot")
  485. ns.SLOT_OFFHAND = GetInventorySlotInfo("SecondaryHandSlot")
  486. ns.SLOT_TABARD = GetInventorySlotInfo("TabardSlot")
  487. ns.SLOT_CHEST = GetInventorySlotInfo("ChestSlot")
  488. ns.SLOT_SHIRT = GetInventorySlotInfo("ShirtSlot")
  489. ns.SLOT_HANDS = GetInventorySlotInfo("HandsSlot")
  490. ns.SLOT_WAIST = GetInventorySlotInfo("WaistSlot")
  491. ns.SLOT_SHOULDER = GetInventorySlotInfo("ShoulderSlot")
  492. ns.SLOT_FEET = GetInventorySlotInfo("FeetSlot")
  493. ns.SLOT_ROBE = -99 -- Magic!
  494.  
  495. ns.slot_removals = {
  496.     INVTYPE_WEAPON = {ns.SLOT_MAINHAND},
  497.     INVTYPE_2HWEAPON = {ns.SLOT_MAINHAND},
  498.     INVTYPE_BODY = {ns.SLOT_TABARD, ns.SLOT_CHEST, ns.SLOT_SHOULDER, ns.SLOT_OFFHAND, ns.SLOT_WAIST},
  499.     INVTYPE_CHEST = {ns.SLOT_TABARD, ns.SLOT_OFFHAND, ns.SLOT_WAIST, ns.SLOT_SHIRT},
  500.     INVTYPE_ROBE = {ns.SLOT_TABARD, ns.SLOT_WAIST, ns.SLOT_SHOULDER, ns.SLOT_OFFHAND},
  501.     INVTYPE_LEGS = {ns.SLOT_TABARD, ns.SLOT_WAIST, ns.SLOT_FEET, ns.SLOT_ROBE, ns.SLOT_MAINHAND, ns.SLOT_OFFHAND},
  502.     INVTYPE_WAIST = {ns.SLOT_MAINHAND, ns.SLOT_OFFHAND},
  503.     INVTYPE_FEET = {ns.SLOT_ROBE},
  504.     INVTYPE_WRIST = {ns.SLOT_HANDS, ns.SLOT_CHEST, ns.SLOT_ROBE, ns.SLOT_SHIRT, ns.SLOT_OFFHAND},
  505.     INVTYPE_HAND = {ns.SLOT_OFFHAND},
  506.     INVTYPE_TABARD = {ns.SLOT_WAIST, ns.SLOT_OFFHAND},
  507. }
  508. ns.always_remove = {
  509.     INVTYPE_WEAPON = true,
  510.     INVTYPE_2HWEAPON = true,
  511. }
  512.  
  513. ns.slot_facings = {
  514.     INVTYPE_HEAD = 0,
  515.     INVTYPE_SHOULDER = 0,
  516.     INVTYPE_CLOAK = 3.4,
  517.     INVTYPE_CHEST = 0,
  518.     INVTYPE_ROBE = 0,
  519.     INVTYPE_WRIST = 0,
  520.     INVTYPE_2HWEAPON = 1.6,
  521.     INVTYPE_WEAPON = 1.6,
  522.     INVTYPE_WEAPONMAINHAND = 1.6,
  523.     INVTYPE_WEAPONOFFHAND = -0.7,
  524.     INVTYPE_SHIELD = -0.7,
  525.     INVTYPE_HOLDABLE = -0.7,
  526.     INVTYPE_RANGED = 1.6,
  527.     INVTYPE_RANGEDRIGHT = 1.6,
  528.     INVTYPE_THROWN = 1.6,
  529.     INVTYPE_HAND = 0,
  530.     INVTYPE_WAIST = 0,
  531.     INVTYPE_LEGS = 0,
  532.     INVTYPE_FEET = 0,
  533.     INVTYPE_TABARD = 0,
  534.     INVTYPE_BODY = 0,
  535. }
  536.  
  537. ns.modifiers = {
  538.     Shift = IsShiftKeyDown,
  539.     Ctrl = IsControlKeyDown,
  540.     Alt = IsAltKeyDown,
  541.     None = function() return true end,
  542. }
  543.  
  544. -- Utility fun
  545.  
  546. --/dump C_Transmog.GetItemInfo(GetItemInfoInstant(""))
  547. function ns.CanTransmogItem(itemLink)
  548.     local itemID = GetItemInfoInstant(itemLink)
  549.     if itemID then
  550.         local canBeChanged, noChangeReason, canBeSource, noSourceReason = C_Transmog.GetItemInfo(itemID)
  551.         return canBeSource, noSourceReason
  552.     end
  553. end
  554.  
  555. function ns.PlayerHasAppearance(item)
  556.     if not ns.CanTransmogItem(item) then
  557.         return false, false, true
  558.     end
  559.     local state = ns.CheckTooltipFor(item, TRANSMOGRIFY_TOOLTIP_APPEARANCE_UNKNOWN, TRANSMOGRIFY_TOOLTIP_ITEM_UNKNOWN_APPEARANCE_KNOWN)
  560.     if state == TRANSMOGRIFY_TOOLTIP_APPEARANCE_UNKNOWN then
  561.         return
  562.     end
  563.     return true, state == TRANSMOGRIFY_TOOLTIP_ITEM_UNKNOWN_APPEARANCE_KNOWN
  564. end
  565.  
  566. do
  567.     local tooltip
  568.     function ns.CheckTooltipFor(link, ...)
  569.         if not tooltip then
  570.             tooltip = CreateFrame("GameTooltip", "AppearanceTooltipScanningTooltip", nil, "GameTooltipTemplate")
  571.             tooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
  572.         end
  573.         tooltip:ClearLines()
  574.  
  575.         -- just showing tooltip for an itemid
  576.         -- uses rather innocent checking so that slot can be a link or an itemid
  577.         local link = tostring(link) -- so that ":match" is guaranteed to be okay
  578.         if not link:match("item:") then
  579.             link = "item:"..link
  580.         end
  581.         tooltip:SetHyperlink(link)
  582.  
  583.         for i=2, tooltip:NumLines() do
  584.             local left = _G["AppearanceTooltipScanningTooltipTextLeft"..i]
  585.             --local right = _G["AppearanceTooltipScanningTooltipTextRight"..i]
  586.             if left and left:IsShown() then
  587.                 local text = left:GetText()
  588.                 for ii=1, select('#', ...) do
  589.                     if string.match(text, (select(ii, ...))) then
  590.                         return text
  591.                     end
  592.                 end
  593.             end
  594.             --if right and right:IsShown() and string.match(right:GetText(), text) then return true end
  595.         end
  596.         return false
  597.     end
  598. end
  599.  
  600. function ns.Print(...) print("|cFF33FF99".. myfullname.. "|r:", ...) end
  601.  
  602. local debugf = tekDebug and tekDebug:GetFrame(myname)
  603. function ns.Debug(...) if debugf then debugf:AddMessage(string.join(", ", tostringall(...))) end end
  604.  
  605. function setDefaults(options, defaults)
  606.     setmetatable(options, { __index = function(t, k)
  607.         if type(defaults[k]) == "table" then
  608.             t[k] = setDefaults({}, defaults[k])
  609.             return t[k]
  610.         end
  611.         return defaults[k]
  612.     end, })
  613.     return options
  614. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement