You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2139 lines
73 KiB

---- Extra Features For PerksProgramFrame
local _, addon = ...
local DataProvider = addon.PerksProgramDataProvider;
local TransmogDataProvider = addon.TransmogDataProvider;
local L = Narci.L;
local NarciAPI = NarciAPI;
local BlizzardFrame;
local PerksProgramUITooltip;
local ExtraDetailFrame; --1.Display the items of an ensemble on ProductDetailsContainerFrame 2.Toggle individual item's visibility.
local SheatheToggle;
local AnimationButton, AnimationDropDown;
local SELECTED_DATA;
local C_Item = C_Item;
local GetItemInfoInstant = C_Item.GetItemInfoInstant;
local C_PerksProgram = C_PerksProgram;
local C_TransmogCollection = C_TransmogCollection;
local EventRegistry = EventRegistry;
local hooksecurefunc = hooksecurefunc;
local After = C_Timer.After;
-- User Settings --
local CHANGE_POSE = false; --Change the default model's animation and yaw
local DEV_MODE = false;
-------------------
local CURRENCY_MARKUP = " |T4696085:0:0:0:0:64:64:6:58:6:58|t";
local STAND_ANIMATION = 804; --Stand Character Create
local MOUNT_SPECIAL_ANIM_KIT = 1371; --See https://www.townlong-yak.com/framexml/live/Blizzard_PerksProgram/Blizzard_PerksProgramModel.lua
local MODEL_SETUPS = {
INVTYPE_RANGED = {yaw = -1.52, animation = STAND_ANIMATION, sheathed = false},
INVTYPE_2HWEAPON = {yaw = 0.00, animation = STAND_ANIMATION, sheathed = false},
INVTYPE_WEAPON = {yaw = -2.10, animation = STAND_ANIMATION, sheathed = false},
INVTYPE_RANGEDRIGHT = {yaw = -1.83, animation = STAND_ANIMATION, sheathed = false},
STAFF = {yaw = 2.13, animation = STAND_ANIMATION, sheathed = true},
};
local function GetPlayerActor()
return BlizzardFrame.ModelSceneContainerFrame.playerActor
end
local function SetupModelByItemID(actor, itemID)
if itemID then
local _, _, _, itemEquipLoc, _, classID, subclassID = GetItemInfoInstant(itemID);
local key = itemEquipLoc;
if classID == 2 and subclassID == 10 then
key = "STAFF";
end
local data = key and MODEL_SETUPS[key];
if data then
if data.yaw then
actor:SetYaw(data.yaw);
end
if data.sheathed ~= nil then
actor:SetSheathed(data.sheathed);
end
end
local animationID = (data and data.animation) or STAND_ANIMATION;
actor:StopAnimationKit();
actor:SetAnimationBlendOperation(0); --LE_MODEL_BLEND_OPERATION_ANIM
actor:SetAnimation(animationID);
local sheathed = actor:GetSheathed(); --Re-sheathe so the actor can grip the weapon
actor:SetSheathed(not sheathed);
actor:SetSheathed(sheathed);
end
end
local function GetColorizedItemNameFromSource(sourceID, itemID)
if not itemID then
itemID = C_TransmogCollection.GetSourceItemID(sourceID);
end
if itemID then
local itemName, itemLink, itemQuality = C_Item.GetItemInfo(itemID);
if itemName and itemName ~= "" then
local hex = NarciAPI.GetItemQualityHexColor(itemQuality);
return "|cff"..hex..itemName.."|r", true
else
return itemID, false
end
end
end
local function SetButtonFontColor(fontString, colorIndex)
if colorIndex == 1 then
fontString:SetTextColor(0.5, 0.5, 0.5);
elseif colorIndex == 2 then
fontString:SetTextColor(1, 1, 1);
elseif colorIndex == 3 then
fontString:SetTextColor(1, 0.82, 0);
end
end
local function GetSelectedMountTypeName()
local data = SELECTED_DATA;
if not (data and data.mountID and data.mountID ~= 0) then return end;
local mountTypeID = select(5, C_MountJournal.GetMountInfoExtraByID(data.mountID));
local mountTypeName;
if mountTypeID == 230 then --ground
mountTypeName = MOUNT_JOURNAL_FILTER_GROUND or "Ground";
elseif mountTypeID == 248 then --flying
mountTypeName = MOUNT_JOURNAL_FILTER_FLYING or "Flying";
end
return mountTypeName
end
local function UpdateProductModelAnimation(data, userInput)
local categoryID = data.perksVendorCategoryID;
if categoryID == 1 then --Transmog
if CHANGE_POSE then
local actor = PerksProgramFrame.ModelSceneContainerFrame.playerActor;
if actor then
SetupModelByItemID(actor, data.itemID);
end
if userInput then
actor:SetAnimation(0);
AnimationDropDown:SelectAnimationByIndex(1);
end
end
elseif categoryID == 2 then --Mount
local actor = PerksProgramFrame.ModelSceneContainerFrame.MainModelScene:GetActorByTag("mount");
if actor then
if not CHANGE_POSE then
actor:PlayAnimationKit(MOUNT_SPECIAL_ANIM_KIT);
if userInput then
AnimationDropDown:SelectAnimationByIndex(AnimationDropDown.maxIndex);
end
elseif userInput then
actor:SetAnimation(0);
AnimationDropDown:SelectAnimationByIndex(1);
end
end
elseif categoryID == 3 then --Pet
end
end
local function OnProductSelectedAfterModel(f, data)
--Enum.PerksVendorCategoryType
SELECTED_DATA = data;
local categoryID = data.perksVendorCategoryID;
local showExtraDetail;
local showSheatheToggle = true;
UpdateProductModelAnimation(data);
if categoryID == 8 then --TransmogSet
--[[ --Showing child items has become a base feature
if data.transmogSetID then
ExtraDetailFrame:Show();
local sourceIDs = C_TransmogSets.GetAllSourceIDs(data.transmogSetID);
ExtraDetailFrame:DisplayEnsembleSources(sourceIDs);
showExtraDetail = true;
end
--]]
elseif categoryID == 3 then --Pet
if data.speciesID then
ExtraDetailFrame:DisplayPetInfo(data.speciesID);
showExtraDetail = true;
end
showSheatheToggle = false;
elseif categoryID == 2 then --Mounts
--Mount: Add mountType (Ground, Flying, etc.) to CategoryText
--Now implemented by Blizzard
--[[
showSheatheToggle = false;
local mountTypeName = GetSelectedMountTypeName();
if mountTypeName then
local defaultDetailsFrame = ExtraDetailFrame.parentFrame; --PerksProgramDetailsFrameTemplate
if defaultDetailsFrame and defaultDetailsFrame.CategoryText then
After(0, function() --DetailsFrame also use EventRegistry for updating data, so we need to set a delay
mountTypeName = GetSelectedMountTypeName();
if mountTypeName then
defaultDetailsFrame.CategoryText:SetText((PERKS_VENDOR_CATEGORY_MOUNT or "Mount").." - "..mountTypeName);
end
end);
end
end
--]]
elseif categoryID == 1 then --Transmog
local sourceID = data.itemModifiedAppearanceID;
local ownerSetInfo = TransmogDataProvider:GetOwnerSetInfo(sourceID);
if ownerSetInfo then
ExtraDetailFrame:Show();
ExtraDetailFrame:DisplayHiddenTransmogSet(ownerSetInfo, sourceID);
showExtraDetail = true;
end
end
if not showExtraDetail then
ExtraDetailFrame:Hide();
end
if ExtraDetailFrame.parentFrame then
ExtraDetailFrame.parentFrame:Layout();
end
if SheatheToggle then
SheatheToggle:SetState(categoryID);
end
AnimationDropDown:UpdateOptions();
end
local function GetPetTypeTexture(petTypeID, size)
size = size or 16;
if petTypeID and PET_TYPE_SUFFIX and PET_TYPE_SUFFIX[petTypeID] then
return string.format("|T%s:%d:%d:0:0:128:256:102:63:129:168|t", "Interface/PetBattles/PetIcon-"..PET_TYPE_SUFFIX[petTypeID], size, size);
else
return "";
end
end
local function SetupPetTooltip(tooltip, speciesID)
local petAbilityLevelInfo = C_PetJournal.GetPetAbilityListTable(speciesID);
if petAbilityLevelInfo and #petAbilityLevelInfo > 0 then
tooltip:AddLine(" ");
local name, icon, typeID;
local typeIconFomart = "|T%s:24:24|t|T%s:16:16:-4:0:128:256:102:63:129:168|t";
for _, info in ipairs(petAbilityLevelInfo) do
name, icon, typeID = C_PetJournal.GetPetAbilityInfo(info.abilityID);
icon = string.format(typeIconFomart, icon, "Interface/PetBattles/PetIcon-"..PET_TYPE_SUFFIX[typeID]);
tooltip:AddLine(icon.." "..name, 1, 1, 1, true);
end
tooltip:Show();
end
--_G["BATTLE_PET_NAME_"..typeID]
end
local PET_ABILITY_INFO;
local function InitPetAbilityInfo()
if not PET_ABILITY_INFO then
PET_ABILITY_INFO = SharedPetBattleAbilityTooltip_GetInfoTable();
function PET_ABILITY_INFO:GetPetType()
return self.petType
end
function PET_ABILITY_INFO:GetAbilityID()
return self.abilityID;
end
function PET_ABILITY_INFO:IsInBattle()
return false;
end
function PET_ABILITY_INFO:GetHealth(target)
self:EnsureTarget(target);
return self.maxHealth;
end
function PET_ABILITY_INFO:GetMaxHealth(target)
self:EnsureTarget(target);
return self.maxHealth;
end
function PET_ABILITY_INFO:GetAttackStat(target)
self:EnsureTarget(target);
return self.power;
end
function PET_ABILITY_INFO:GetSpeedStat(target)
self:EnsureTarget(target);
return self.speed;
end
function PET_ABILITY_INFO:EnsureTarget(target)
end
end
end
local function SetupPetAbilityTooltip(owner, abilityID, level)
InitPetAbilityInfo();
local id, name, icon, maxCooldown, unparsedDescription, numTurns, petType, noStrongWeakHints = C_PetBattles.GetAbilityInfoByID(abilityID);
local tooltip = PerksProgramUITooltip;
tooltip:Hide();
tooltip:SetOwner(owner, "ANCHOR_NONE");
tooltip:SetPoint("TOPLEFT", owner, "BOTTOMLEFT", -2, -4);
local petTypeIcon = GetPetTypeTexture(petType, 24);
tooltip:SetText(petTypeIcon.." "..name);
if level then
tooltip:AddLine(string.format(ITEM_MIN_LEVEL, level), 0.6, 0.6, 0.6, true);
end
if numTurns and numTurns > 1 then
tooltip:AddLine(string.format(BATTLE_PET_ABILITY_MULTIROUND, numTurns), 1, 1, 1, true);
end
if maxCooldown and maxCooldown > 0 then
tooltip:AddLine(string.format(PET_BATTLE_TURN_COOLDOWN, maxCooldown), 1, 1, 1, true);
end
if unparsedDescription then
PET_ABILITY_INFO.abilityID = abilityID;
PET_ABILITY_INFO.speciesID = 1;
PET_ABILITY_INFO.petID = nil;
PET_ABILITY_INFO.petType = petType;
PET_ABILITY_INFO.power = 0;
PET_ABILITY_INFO.speed = 0;
PET_ABILITY_INFO.maxHealth = 100;
local description = SharedPetAbilityTooltip_ParseText(PET_ABILITY_INFO, unparsedDescription);
tooltip:AddLine(description, 1, 0.82, 0, true);
end
tooltip:Show();
SharedTooltip_SetBackdropStyle(tooltip, GAME_TOOLTIP_BACKDROP_STYLE_DEFAULT_DARK);
end
local function PerksProgramTooltip_ProcessInfo(f, info)
--SharedTooltip_SetBackdropStyle(f, GAME_TOOLTIP_BACKDROP_STYLE_DEFAULT_DARK);
local owner = f:GetOwner(); --ScrollViewButton
if not owner then return end;
local viid = owner.perksVendorItemID;
if (not viid) and owner.GetElementData then
local data = owner:GetElementData();
viid = data and data.perksVendorItemID;
end
if viid then
local sourceID = DataProvider:GetVendorItemTransmogSourceID(viid);
if sourceID and TransmogDataProvider:IsSoucePartOfTransmogSet(sourceID) then
f:AddLine(" ");
f:AddLine(string.format(L["Format Item Belongs To Set"], TransmogDataProvider:GetOwnerSetName(sourceID)), 1, 0.82, 0, true);
end
--[[
if not owner.purchased then
--Show "unavailable" for historical items
local seconds = C_PerksProgram.GetTimeRemaining(viid);
if seconds and seconds <= 0 then
f:AddLine(L["Perks Program Item Unavailable"], 0.6, 0.6, 0.6, true);
f:Show();
end
end
--Show month name for returning items
local displayMonthName, isNewItem = DataProvider:GetVendorItemAddedMonthName(viid);
if (not isNewItem) and displayMonthName then
f:AddLine(" ");
f:AddLine(string.format(L["Perks Program Item Added In Format"], displayMonthName), 1, 0.82, 0, true);
end
--]]
end
end
local function PerksProgramCurrencyFrame_OnEnter(f)
--PerksProgramCurrencyFrame
--Constants.CurrencyConsts.CURRENCY_ID_PERKS_PROGRAM_DISPLAY_INFO
local unclaimedPoints, unearnedPoints = DataProvider:GetAvailableCurrency(); --Sometimes returns a large negative value for some reason
if unclaimedPoints > 0 or unearnedPoints > 0 then
local numLines = PerksProgramUITooltip:NumLines();
local fontString, stringText;
for i = 4, numLines do
fontString = _G["PerksProgramTooltipTextLeft"..i];
if fontString then
stringText = fontString:GetText();
if stringText ~= "" then
if (stringText == _G.PERKS_PROGRAM_UNCOLLECTED_TENDER) and unclaimedPoints > 0 then
fontString:SetText(string.format(L["Perks Program Unclaimed Tender Format"], unclaimedPoints));
elseif (stringText == _G.PERKS_PROGRAM_ACTIVITIES_UNEARNED) and unearnedPoints > 0 then
fontString:SetText(string.format(L["Perks Program Unearned Tender Format"], unearnedPoints));
end
end
end
end
PerksProgramUITooltip:Show();
end
end
local function CreateDevTool(owner)
local f = CreateFrame("Frame", nil, owner);
f:SetSize(16, 16);
f:SetPoint("TOP", owner, "TOP", 0, -16);
local line1 = f:CreateFontString(nil, "OVERLAY", "SystemFont_Shadow_Med3_Outline");
line1:SetJustifyH("CENTER");
line1:SetPoint("TOP", f, "TOP", 0, 0);
line1:SetTextColor(1, 0.82, 0);
local line2 = f:CreateFontString(nil, "OVERLAY", "SystemFont_Shadow_Med3_Outline");
line2:SetJustifyH("CENTER");
line2:SetPoint("TOP", f, "TOP", 0, -20);
line2:SetTextColor(1, 0.82, 0);
local function OnUpdate(self, elapsed)
self.t = self.t + elapsed;
if self.t > 0.2 then
self.t = 0;
local actorYaw = 0;
local cameraYaw = 0;
local effectiveYaw = 0;
if self.actor then
actorYaw = self.actor:GetYaw();
end
if self.camera then
cameraYaw = self.camera:GetYaw();
end
if self.baseCameraYaw then
local delta = cameraYaw - self.baseCameraYaw;
effectiveYaw = actorYaw - delta;
end
line2:SetText(string.format("Actor: |cffffffff%.2f|r Camera: |cffffffff%.2f|r Effective: |cffffffff%.2f|r", actorYaw, cameraYaw, effectiveYaw));
end
end
f.t = 0;
f:SetScript("OnUpdate", OnUpdate);
local function Callback(_, data)
f.actor = GetPlayerActor();
local DEFAULT_CAMERA_TAG = "primary";
f.camera = BlizzardFrame.ModelSceneContainerFrame.PlayerModelScene:GetCameraByTag(DEFAULT_CAMERA_TAG);
f.baseCameraYaw = f.camera:GetYaw();
local itemID = data.itemID;
local _, _, _, itemEquipLoc, _, classID, subclassID = GetItemInfoInstant(itemID);
itemEquipLoc = itemEquipLoc or "NOT_Equippable";
line1:SetText(string.format("ItemID: |cffffffff%s|r EquipLoc: |cffffffff%s|r Class: |cffffffff%s/%s|r", itemID, itemEquipLoc, classID, subclassID));
end
EventRegistry:RegisterCallback("PerksProgramModel.OnProductSelectedAfterModel", Callback, f);
end
local function Initialize()
if not PerksProgramFrame then return end;
BlizzardFrame = PerksProgramFrame;
CHANGE_POSE = NarcissusDB.TradingPostChangePost;
if DEV_MODE then
CreateDevTool(BlizzardFrame);
end
--Insert ExtraDetailFrame
if BlizzardFrame.ProductsFrame and BlizzardFrame.ProductsFrame.PerksProgramProductDetailsContainerFrame and BlizzardFrame.ProductsFrame.PerksProgramProductDetailsContainerFrame.DetailsFrame then
ExtraDetailFrame.parentFrame = BlizzardFrame.ProductsFrame.PerksProgramProductDetailsContainerFrame.DetailsFrame;
ExtraDetailFrame:SetParent(ExtraDetailFrame.parentFrame);
end
--Skin Tooltip
PerksProgramUITooltip = BlizzardFrame.PerksProgramTooltip;
if PerksProgramUITooltip and PerksProgramUITooltip.ProcessInfo then
--PerksProgramUITooltip.layoutType = "TooltipDefaultDarkLayout";
hooksecurefunc(PerksProgramUITooltip, "ProcessInfo", PerksProgramTooltip_ProcessInfo);
if BlizzardFrame.ProductsFrame.PerksProgramCurrencyFrame then
BlizzardFrame.ProductsFrame.PerksProgramCurrencyFrame:HookScript("OnEnter", PerksProgramCurrencyFrame_OnEnter);
end
end
if BlizzardFrame.TimeLeftListFormatter then
--Hide TimeRemaining when browsing history items
function BlizzardFrame.TimeLeftListFormatter:FormatZero()
return ""
end
end
--Change the rotation speed
if BlizzardFrame.FooterFrame and BlizzardFrame.FooterFrame.RotateButtonContainer then
local period = 4;
local f = BlizzardFrame.FooterFrame.RotateButtonContainer;
local increment = math.floor(1000* 2*math.pi/period/60)/1000;
if f.RotateLeftButton then
f.RotateLeftButton.rotationIncrement = increment;
else
return
end
if f.RotateRightButton then
f.RotateRightButton.rotationIncrement = increment;
else
return
end
f.RotateLeftButton:ClearAllPoints();
f.RotateRightButton:ClearAllPoints();
f.RotateRightButton:SetPoint("RIGHT", f, "CENTER", -8, 0);
f.RotateLeftButton:SetPoint("RIGHT", f.RotateRightButton, "LEFT", -4, 0);
SheatheToggle = CreateFrame("Button", nil, f, "NarciPerksProgramSquareButtonTemplate");
SheatheToggle:SetPoint("LEFT", f, "CENTER", 8, 0);
SheatheToggle.Icon:SetTexture("Interface/AddOns/Narcissus/Art/Modules/PerksProgram/SheatheIconYellow");
local function SheatheToggle_SetIcon(b, sheathed)
if sheathed then
b.Icon:SetTexCoord(0, 0.5, 0, 1);
else
b.Icon:SetTexCoord(0.5, 1, 0, 1);
end
end
SheatheToggle_SetIcon(SheatheToggle, true);
local function SheatheToggle_OnClick(b)
local playerActor = GetPlayerActor();
if not playerActor then return end;
local sheathed = not playerActor:GetSheathed();
playerActor:SetSheathed(sheathed);
SheatheToggle_SetIcon(b, sheathed);
end
local function SheatheToggle_OnKeyDown(b, key, down)
if b:IsEnabled() then
if b.hotkey == key then
SheatheToggle_OnClick(b);
b:SetPropagateKeyboardInput(false);
return
end
end
b:SetPropagateKeyboardInput(true);
end
local function SheatheToggle_OnShow(b)
local hotkey = GetBindingKey("TOGGLESHEATH");
b.hotkey = hotkey;
if hotkey then
b.tooltipText = BINDING_NAME_TOGGLESHEATH.." |cffffd100("..hotkey..")|r";
b:SetScript("OnKeyDown", SheatheToggle_OnKeyDown);
else
b.tooltipText = BINDING_NAME_TOGGLESHEATH;
b:SetScript("OnKeyDown", nil);
end
end
local function SheatheToggle_OnHide(b)
b:SetScript("OnKeyDown", nil);
end
SheatheToggle:SetScript("OnShow", SheatheToggle_OnShow);
SheatheToggle:SetScript("OnHide", SheatheToggle_OnHide);
function SheatheToggle:SetState(perksVendorCategoryID)
local enable = perksVendorCategoryID and (perksVendorCategoryID ~= 2) and (perksVendorCategoryID ~= 3);
local playerActor = GetPlayerActor();
enable = enable and (playerActor and playerActor:IsShown());
local sheathed = playerActor and playerActor:GetSheathed();
SheatheToggle_SetIcon(self, sheathed);
if enable then
self:Enable();
else
self:Disable();
end
end
SheatheToggle.onClickFunc = SheatheToggle_OnClick;
SheatheToggle:SetState(SELECTED_DATA and SELECTED_DATA.perksVendorCategoryID);
SheatheToggle_OnShow(SheatheToggle);
AnimationButton = CreateFrame("Button", nil, f, "NarciPerksProgramSquareButtonTemplate");
AnimationButton:SetPoint("LEFT", SheatheToggle, "RIGHT", 4, 0);
AnimationButton.Icon:SetTexture("Interface/AddOns/Narcissus/Art/Modules/PerksProgram/AnimationIcon");
AnimationDropDown:SetParentButton(AnimationButton);
AnimationDropDown:UpdateOptions();
local function AnimationButton_OnClick(b)
if AnimationDropDown:IsShown() then
AnimationDropDown:Hide();
else
AnimationDropDown:ShowFrame();
end
end
AnimationButton.onClickFunc = AnimationButton_OnClick;
local function SkinSmallButton(button, checkTexture, disabledCheckTexture)
button:SetSize(48, 48);
button:SetNormalAtlas("perks-button-up");
button:SetPushedAtlas("perks-button-down");
button:SetHighlightAtlas("perks-button-up");
local pushedTex = button:GetPushedTexture();
pushedTex:SetPoint("CENTER", button, "CENTER", 1, -1);
local tex1 = button:GetCheckedTexture(); --Texture, not fileID
if tex1 then
tex1:ClearAllPoints();
tex1:SetPoint("CENTER", button, "CENTER", 0, 0);
tex1:SetSize(24, 24);
tex1:SetAtlas(checkTexture);
end
local tex2 = button:GetDisabledCheckedTexture();
if tex2 then
tex2:ClearAllPoints();
tex2:SetPoint("CENTER", button, "CENTER", 0, 0);
tex2:SetSize(24, 24);
tex2:SetAtlas(disabledCheckTexture);
end
button.Text:Hide();
end
local PlayerToggle = BlizzardFrame.FooterFrame.TogglePlayerPreview;
--[[
if PlayerToggle then
SkinSmallButton(PlayerToggle, "common-icon-checkmark-yellow", "common-icon-checkmark");
PlayerToggle:ClearAllPoints();
PlayerToggle:SetPoint("RIGHT", f.RotateLeftButton, "LEFT", -32, 0);
end
--]]
end
end
NarciPerksProgramItemDetailExtraFrameMixin = {};
function NarciPerksProgramItemDetailExtraFrameMixin:OnLoad()
ExtraDetailFrame = self;
if not DataProvider:DoesPerksProgramExist() then return end;
self:RegisterEvent("PERKS_PROGRAM_OPEN");
self:RegisterEvent("PERKS_PROGRAM_CLOSE");
self:SetEnsembleHeaderText();
EventRegistry:RegisterCallback("PerksProgramModel.OnProductSelectedAfterModel", OnProductSelectedAfterModel, ExtraDetailFrame);
EventRegistry:RegisterCallback("PerksProgramFrame.OnShow", self.LoadUserSettings, self);
end
function NarciPerksProgramItemDetailExtraFrameMixin:Init()
self.Init = nil;
if BlizzardFrame.ConfirmPurchase and BlizzardFrame.GetSelectedProduct then
hooksecurefunc("StaticPopup_Show", function(which)
if which == "PERKS_PROGRAM_CONFIRM_PURCHASE" then
self:TryShowPurchaseAlert();
end
end)
if StaticPopup1 then
StaticPopup1:HookScript("OnHide", function()
self:HidePurchaseAlert();
end);
end
end
if BlizzardFrame.ToggleHideArmorSetting then
hooksecurefunc(BlizzardFrame, "ToggleHideArmorSetting", function(_, playerArmorSetting)
DataProvider:SaveUserData("hidePlayerArmorSetting", playerArmorSetting);
end)
end
local att = self.AutoTryOnToggle;
self.autoDisplayTransmogSet = DataProvider:GetTimeLimitedData("autoDisplayTransmogSet");
local function att_UpdateVisual()
if self.autoDisplayTransmogSet then
att.Checkbox:SetTexCoord(0, 0.5, 0, 1);
else
att.Checkbox:SetTexCoord(0.5, 1, 0, 1);
end
end
do
local function OnClick()
self:ToggleAutoDisplayTransmogSet();
att_UpdateVisual();
end
local function OnEnter()
att.ButtonText:SetTextColor(1, 1, 1);
end
local function OnLeave()
att.ButtonText:SetTextColor(0.67, 0.67, 0.67);
end
att:SetScript("OnClick", OnClick);
att:SetScript("OnEnter", OnEnter);
att:SetScript("OnLeave", OnLeave);
OnLeave();
att_UpdateVisual();
end
att.ButtonText:SetText(L["Auto Try On All Items"]);
local buttonWidth = att:GetWidth();
local checkboxSize = 40;
local textWidth = att.ButtonText:GetWrappedWidth();
local visualCompensation = -8;
local gap = -2;
local offsetX = 0.5*(buttonWidth - checkboxSize - textWidth + visualCompensation);
att.Checkbox:ClearAllPoints();
att.Checkbox:SetPoint("LEFT", att, "LEFT", offsetX, 0);
att.ButtonText:ClearAllPoints();
att.ButtonText:SetPoint("LEFT", att.Checkbox, "RIGHT", gap, 0);
do
local HeaderMouseoverFrame = self.HeaderMouseoverFrame;
local function FitToText(f)
local width = self.HeaderText:GetWrappedWidth();
f:SetWidth(width + 16);
end
local function OnEnter(f)
if self.sourceIDs then
local n = 0;
local itemCosts = {};
local totalCosts = 0;
local price, purchased;
local name, loaded;
local allLoaded = true;
for _, sourceID in ipairs(self.sourceIDs) do
name, loaded = GetColorizedItemNameFromSource(sourceID);
if name then
allLoaded = allLoaded and loaded;
price, purchased = DataProvider:GetVendorItemPriceBySourceID(sourceID);
if purchased then
n = n + 1;
itemCosts[n] = {name, 0};
elseif price and price > 0 then
n = n + 1;
itemCosts[n] = {name, price};
totalCosts = totalCosts + price;
end
end
end
if n > 0 then
local tooltip = PerksProgramUITooltip;
tooltip:Hide();
tooltip:SetOwner(self, "ANCHOR_NONE");
tooltip:SetPoint("BOTTOMRIGHT", self, "TOPLEFT", -8, 0);
if totalCosts > 0 then
tooltip:AddDoubleLine(L["Full Set Cost"], totalCosts..CURRENCY_MARKUP, 1, 0.82, 0, 1, 1, 1);
else
tooltip:AddDoubleLine(L["Full Set Cost"], "|A:perks-owned-small:0:0|a", 1, 0.82, 0, 1, 1, 1);
end
for _, data in ipairs(itemCosts) do
if data[2] > 0 then
tooltip:AddDoubleLine(data[1], data[2]..CURRENCY_MARKUP, 1, 1, 1, 1, 1, 1); --interface/icons/tradingpostcurrency.blp
else
tooltip:AddDoubleLine(data[1], "|A:perks-owned-small:0:0|a", 1, 1, 1, 1, 1, 1);
end
end
tooltip:Show();
if not allLoaded then
After(0.2, function()
if f:IsVisible() and f:IsMouseOver() then
OnEnter(f);
end
end);
end
end
end
end
local function OnLeave(f)
PerksProgramUITooltip:Hide();
end
HeaderMouseoverFrame.FitToText = FitToText;
HeaderMouseoverFrame:SetScript("OnEnter", OnEnter);
HeaderMouseoverFrame:SetScript("OnLeave", OnLeave);
end
do --Fixed Mount Speical, Attack Animation Checkboxes status not saved issue
--NOTE: We instead disable the two checkboxes because we already have equivalents (animation dropdown)
local ff = BlizzardFrame.FooterFrame;
local mc = BlizzardFrame.ModelSceneContainerFrame;
if BlizzardFrame.SetMountSpecialPreviewOnClick then
BlizzardFrame:SetMountSpecialPreviewOnClick(false);
end
if BlizzardFrame.PlayerSetAttackAnimationOnClick then
BlizzardFrame:PlayerSetAttackAnimationOnClick(false);
end
if mc and ff.ToggleHideArmor and ff.TogglePlayerPreview then
local function HideCheckboxes()
ff.ToggleHideArmor:SetPoint("LEFT", ff.RotateButtonContainer, "LEFT", -18, 0);
ff.TogglePlayerPreview:SetPoint("LEFT", ff.RotateButtonContainer, "LEFT", -18, 0);
if ff.ToggleMountSpecial then
ff.ToggleMountSpecial:Hide();
end
if ff.ToggleAttackAnimation then
ff.ToggleAttackAnimation:Hide();
end
end
After(0, function()
EventRegistry:UnregisterCallback("PerksProgram.OnMountSpecialPreviewSet", PerksProgramFrame.ModelSceneContainerFrame);
EventRegistry:UnregisterCallback("PerksProgram.OnPlayerAttackAnimationSet", PerksProgramFrame.ModelSceneContainerFrame);
HideCheckboxes();
end);
end
--This method may not be secure:
C_PerksProgram.IsMountSpecialAnimToggleEnabled = function() return false end;
C_PerksProgram.IsAttackAnimToggleEnabled = function() return false end;
--[[ --The actual fix
if (mc and mc.OnMountSpecialPreviewSet and mc.OnPlayerAttackAnimationSet)
and (BlizzardFrame.SetMountSpecialPreviewOnClick and BlizzardFrame.PlayerSetAttackAnimationOnClick)
and (ff and ff.OnProductSelected and ff.ToggleMountSpecial and ff.ToggleAttackAnimation) then
ff.ToggleMountSpecial:HookScript("OnClick", function(f)
local isChecked = f:GetChecked();
DataProvider:SaveUserData("mountSpecialAnimPlaying", isChecked);
end);
ff.ToggleAttackAnimation:HookScript("OnClick", function(f)
local isChecked = f:GetChecked();
DataProvider:SaveUserData("attackAnimationPlaying", isChecked);
end);
local EventSolver = CreateFrame("Frame", nil, BlizzardFrame);
EventSolver:Hide();
EventSolver:SetScript("OnHide", function()
EventSolver.t = 0;
EventSolver:Hide();
end);
EventSolver:SetScript("OnShow", function()
EventSolver.t = 0;
end);
EventSolver:SetScript("OnUpdate", function(f, elapsed)
f.t = f.t + elapsed;
if f.t > 0 then
f:Hide();
if ff.ToggleMountSpecial:IsShown() then
local isChecked = DataProvider:GetUserData("mountSpecialAnimPlaying");
--BlizzardFrame:SetMountSpecialPreviewOnClick(isChecked);
ff.ToggleMountSpecial:SetChecked(isChecked);
mc:OnMountSpecialPreviewSet(isChecked);
end
if ff.ToggleAttackAnimation:IsShown() then
local isChecked = DataProvider:GetUserData("attackAnimationPlaying");
--BlizzardFrame:PlayerSetAttackAnimationOnClick(isChecked);
ff.ToggleAttackAnimation:SetChecked(isChecked);
mc:OnPlayerAttackAnimationSet(isChecked);
end
end
end);
function EventSolver:Start()
EventSolver.t = 0;
EventSolver:Show();
end
After(0, function()
EventRegistry:UnregisterCallback("PerksProgram.OnMountSpecialPreviewSet", PerksProgramFrame.ModelSceneContainerFrame);
EventRegistry:UnregisterCallback("PerksProgram.OnPlayerAttackAnimationSet", PerksProgramFrame.ModelSceneContainerFrame);
EventRegistry:RegisterCallback("PerksProgramModel.OnProductSelectedAfterModel", function()
EventSolver:Start();
end);
EventRegistry:RegisterCallback("PerksProgram.OnMountSpecialPreviewSet", function()
EventSolver:Start();
end);
EventRegistry:RegisterCallback("PerksProgram.OnPlayerAttackAnimationSet", function()
EventSolver:Start();
end);
EventSolver:Start();
end)
end
--]]
end
end
function NarciPerksProgramItemDetailExtraFrameMixin:OnEvent(event, ...)
if event == "PERKS_PROGRAM_OPEN" then --Alawys ON
self:UnregisterEvent(event);
Initialize();
self:Init();
self:LoadUserSettings();
elseif event == "PERKS_PROGRAM_CLOSE" then --Alawys ON
SELECTED_DATA = nil;
TransmogDataProvider:ClearTransmogSetCache();
self:SaveUserSettings();
elseif event == "PERKS_PROGRAM_PURCHASE_SUCCESS" or event == "PERKS_PROGRAM_REFUND_SUCCESS" then --Dynamic
self:UpdateItemButtons();
end
end
function NarciPerksProgramItemDetailExtraFrameMixin:ReleaseButtons()
if self.buttons then
for i, button in pairs(self.buttons) do
button:ClearData();
end
end
self.Pointer:Hide();
self.Pointer:ClearAllPoints();
self.HeaderMouseoverFrame:Hide();
end
function NarciPerksProgramItemDetailExtraFrameMixin:PointAtButton(button)
if button then
self.Pointer:ClearAllPoints();
self.Pointer:SetPoint("TOP", button, "BOTTOM", 0, 0);
self.Pointer:Show();
end
end
function NarciPerksProgramItemDetailExtraFrameMixin:AcquireSmallButton(i)
if not self.buttons then
self.buttons = {};
end
if not self.buttons[i] then
self.buttons[i] = CreateFrame("Button", nil, self, "NarciPerksProgramItemDetailButtonTemplate");
end
return self.buttons[i];
end
function NarciPerksProgramItemDetailExtraFrameMixin:HideFrame()
if self:IsShown() then
self:Hide();
self:ReleaseButtons();
self.HeaderText:SetText("");
self.sourceIDs = nil;
self.viewedSourceID = nil;
end
end
function NarciPerksProgramItemDetailExtraFrameMixin:CalculateInitialOffset(buttonSize, gap, numButtons, maxButtonPerRow)
local spanX = (buttonSize + gap) * (math.min(numButtons, maxButtonPerRow)) - gap;
return -0.5*spanX;
end
function NarciPerksProgramItemDetailExtraFrameMixin:DisplayPetInfo(speciesID)
self:ReleaseButtons();
self.AutoTryOnToggle:Hide();
if speciesID then
local _, _, petType, _, _, _, _, canBattle = C_PetJournal.GetPetInfoBySpeciesID(speciesID);
local abilities, levels = C_PetJournal.GetPetAbilityList(speciesID);
if (canBattle) and (not abilities) then self:Hide(); return; end;
local numItems = #abilities;
local buttonSize = 32;
local buttonGap = 8;
local verticalGap = 4;
local maxButtonPerRow = 3;
local col, row = 0, 0;
local buttonUnit = buttonSize + buttonGap;
local fromOffsetX = self:CalculateInitialOffset(buttonSize, buttonGap, numItems, maxButtonPerRow);
local button;
for i = 1, numItems do
col = col + 1;
if col > maxButtonPerRow then
col = 1;
row = row + 1;
fromOffsetX = self:CalculateInitialOffset(buttonSize, buttonGap, numItems - row*maxButtonPerRow, maxButtonPerRow);
end
button = self:AcquireSmallButton(i);
button:ClearAllPoints();
button:SetPoint("TOPLEFT", self.HeaderText, "BOTTOM", fromOffsetX + (col - 1) * buttonUnit, -8 -row*(buttonSize + verticalGap));
button:SetPetAbilityInfo(abilities[i], levels[i]);
end
local petTypeName = _G["BATTLE_PET_NAME_"..petType] or "Unknown Type";
local petTypeIcon = GetPetTypeTexture(petType, 16);
petTypeName = petTypeIcon.." "..petTypeName;
if canBattle then
self.HeaderText:SetText(petTypeName);
else
self.HeaderText:SetText(petTypeName.."\n".. BATTLE_PET_CANNOT_BATTLE);
end
local headerHeight = math.floor(self.HeaderText:GetHeight() + 0.5);
if numItems > 0 then
self:SetHeight(headerHeight + 8 + (buttonSize + verticalGap) * (row +1) - verticalGap);
else
self:SetHeight(headerHeight);
end
self:Show();
else
self:Hide();
end
self:UnregisterEvent("PERKS_PROGRAM_PURCHASE_SUCCESS");
self:UnregisterEvent("PERKS_PROGRAM_REFUND_SUCCESS");
end
function NarciPerksProgramItemDetailExtraFrameMixin:SetEnsembleHeaderText(slotName)
if slotName then
self.HeaderText:SetText(slotName);
self.HeaderText:SetTextColor(1, 1, 1);
else
self.HeaderText:SetText(self.defaultHeaderText);
if self.defaultHeaderColor == 1 then
self.HeaderText:SetTextColor(1, 0.82, 0);
else
self.HeaderText:SetTextColor(0.5, 0.5, 0.5);
end
end
end
function NarciPerksProgramItemDetailExtraFrameMixin:DisplayEnsembleSources(sourceIDs, hiddenTransmogSetMode, viewedSourceID)
self:ReleaseButtons();
local extraHeight = 0;
if hiddenTransmogSetMode then
self.AutoTryOnToggle:Show();
extraHeight = 24 + 16;
self.HeaderMouseoverFrame:Show();
else
self.AutoTryOnToggle:Hide();
self.HeaderMouseoverFrame:Hide();
end
local numItems = (sourceIDs and #sourceIDs) or 0;
if numItems > 1 then
local buttonSize = 32;
local buttonGap = 4;
local maxButtonPerRow = 8;
local col, row = 0, 0;
local buttonUnit = buttonSize + buttonGap;
local fromOffsetX = self:CalculateInitialOffset(buttonSize, buttonGap, numItems, maxButtonPerRow);
local fromOffsetY = -22;
local showItemName = hiddenTransmogSetMode == true;
local button;
local sourceID;
for i = 1, numItems do
sourceID = sourceIDs[i];
col = col + 1;
if col > maxButtonPerRow then
col = 1;
row = row + 1;
fromOffsetX = self:CalculateInitialOffset(buttonSize, buttonGap, numItems - row*maxButtonPerRow, maxButtonPerRow);
end
button = self:AcquireSmallButton(i);
button:ClearAllPoints();
button:SetPoint("TOPLEFT", self, "TOP", fromOffsetX + (col - 1) * buttonUnit, fromOffsetY -row*buttonUnit);
button:SetTransmogSource(sourceID);
button.showItemName = showItemName;
if sourceID == viewedSourceID then
self:PointAtButton(button);
end
end
self.defaultHeaderText = L["Include Header"];
self.defaultHeaderColor = 0;
self:SetEnsembleHeaderText();
self:SetHeight(14 + 8 + buttonUnit * (row +1) - buttonGap + extraHeight);
self:Show();
self.numActiveButtons = numItems;
self:RegisterEvent("PERKS_PROGRAM_PURCHASE_SUCCESS");
self:RegisterEvent("PERKS_PROGRAM_REFUND_SUCCESS");
else
self:HideFrame();
self.numActiveButtons = 0;
end
self.sourceIDs = sourceIDs;
self.viewedSourceID = viewedSourceID;
end
function NarciPerksProgramItemDetailExtraFrameMixin:DisplayHiddenTransmogSet(setInfo, viewedSourceID)
local sourceIDs = setInfo.sources;
self:DisplayEnsembleSources(sourceIDs, true, viewedSourceID);
self.defaultHeaderText = setInfo.name;
self.defaultHeaderColor = 1;
self:SetEnsembleHeaderText();
self.HeaderMouseoverFrame:FitToText();
if self.autoDisplayTransmogSet then
local playerActor = GetPlayerActor();
if not playerActor then return end;
for _, sourceID in ipairs(sourceIDs) do
playerActor:TryOn(sourceID);
end
else
end
self:UpdateItemVisibility();
end
function NarciPerksProgramItemDetailExtraFrameMixin:UpdateItemVisibility()
local button;
local hideItem = not self.autoDisplayTransmogSet;
for i = 1, self.numActiveButtons do
button = self.buttons[i];
if button.transmogSourceID == self.viewedSourceID then
button.hideItem = false;
else
button.hideItem = hideItem;
end
button:UpdateVisual();
end
end
function NarciPerksProgramItemDetailExtraFrameMixin:UpdateItemButtons()
After(0.5, function()
local button;
for i = 1, self.numActiveButtons do
button = self.buttons[i];
if button.transmogSourceID then
button.GreenCheck:SetShown(C_TransmogCollection.PlayerKnowsSource(button.transmogSourceID));
end
end
end);
end
function NarciPerksProgramItemDetailExtraFrameMixin:ToggleAutoDisplayTransmogSet()
self.autoDisplayTransmogSet = not self.autoDisplayTransmogSet;
DataProvider:SetTimeLimitedData("autoDisplayTransmogSet", self.autoDisplayTransmogSet);
if self.autoDisplayTransmogSet then
if self.sourceIDs then
local playerActor = GetPlayerActor();
if not playerActor then return end;
for _, sourceID in ipairs(self.sourceIDs) do
playerActor:TryOn(sourceID);
end
end
else
if self.viewedSourceID then
local playerActor = GetPlayerActor();
if not playerActor then return end;
playerActor:Undress();
playerActor:TryOn(self.viewedSourceID);
end
end
self:UpdateItemVisibility();
end
function NarciPerksProgramItemDetailExtraFrameMixin:OnHide()
self:HideFrame();
self:UnregisterEvent("PERKS_PROGRAM_PURCHASE_SUCCESS");
self:UnregisterEvent("PERKS_PROGRAM_REFUND_SUCCESS");
end
function NarciPerksProgramItemDetailExtraFrameMixin:TryShowPurchaseAlert()
if (self:IsVisible() and self.viewedSourceID and self.autoDisplayTransmogSet) then
else
return
end
local product = BlizzardFrame:GetSelectedProduct();
local sourceID = product and product.itemModifiedAppearanceID;
if sourceID == 0 then return end;
local f = self.PurchaseAlertFrame;
if not f then
f = CreateFrame("Frame", nil, self);
self.PurchaseAlertFrame = f;
local scale = 2;
local padding = 4;
local modelWidth = 78 * scale;
local modelHeight = 104 * scale;
f:SetSize(modelWidth + 2*padding, modelHeight + 2*padding);
f:SetPoint("CENTER", UIParent, "CENTER", 0, 0);
NarciAPI.NineSliceUtil.SetUpBorder(f, "genericChamferedBorder", nil, 0.25, 0.25, 0.25, 1, 7);
NarciAPI.NineSliceUtil.SetUpBackdrop(f, "genericChamferedBackground", nil, 0, 0, 0, 0.9, -8);
f.Model = CreateFrame("DressUpModel", nil, f);
f.Model:SetSize(modelWidth, modelHeight);
f.Model:SetPoint("CENTER", 0, 0);
f.Model:SetAutoDress(false);
f.Model:SetDoBlend(false);
NarciAPI.TransitionAPI.SetModelLight( f.Model, true, false, -1, 1, -1, 0.8, 1, 1, 1, 0.5, 1, 1, 1);
f.Model:SetScript("OnModelLoaded", function(m)
if m.cameraID then
Model_ApplyUICamera(f.Model, m.cameraID);
end
if m.sourceID then
m:TryOn(m.sourceID);
end
end)
f.Title = f:CreateFontString(nil, "OVERLAY", "SystemFont_Shadow_Med2_Outline");
f.Title:SetTextColor(1, 0.82, 0);
f.Title:SetJustifyH("CENTER");
f.Title:SetText(L["You Will Receive One Item"]);
f.Title:SetPoint("BOTTOM", f, "TOP", 0, 12);
f:SetFrameStrata("FULLSCREEN_DIALOG");
end
local itemID = C_TransmogCollection.GetSourceItemID(sourceID);
if not itemID then return end;
local Model = f.Model;
Model.cameraID = C_TransmogCollection.GetAppearanceCameraIDBySource(sourceID);
Model:ClearModel();
f:Show();
if NarciAPI.IsHoldableItem(itemID) then
Model.sourceID = nil;
Model:SetItem(itemID, sourceID);
else
Model.sourceID = sourceID;
Model:SetUseTransmogChoices(true);
Model:SetUseTransmogSkin(true);
Model:Undress();
NarciAPI.TransitionAPI.SetModelByUnit(Model, "player");
Model:FreezeAnimation(0, 0, 0);
Model:TryOn(sourceID); --Model must be visible first
end
end
function NarciPerksProgramItemDetailExtraFrameMixin:HidePurchaseAlert()
if self.PurchaseAlertFrame and self.PurchaseAlertFrame:IsShown() then
self.PurchaseAlertFrame:Hide();
end
end
function NarciPerksProgramItemDetailExtraFrameMixin:SaveUserSettings()
--Save the status
end
function NarciPerksProgramItemDetailExtraFrameMixin:LoadUserSettings()
if not BlizzardFrame then return end;
if DataProvider:GetUserData("hidePlayerArmorSetting") and not BlizzardFrame.hidePlayerArmorSetting then
BlizzardFrame.hidePlayerArmorSetting = true;
EventRegistry:TriggerEvent("PerksProgram.OnPlayerHideArmorToggled");
end
end
--Transmog Item Source
local function TransmogItemButton_OnEnter(self)
if self.transmogSourceID then
local itemID = C_TransmogCollection.GetSourceItemID(self.transmogSourceID);
local slotName;
if itemID then
local _, itemType, itemSubType, itemEquipLoc, icon, classID, subclassID = GetItemInfoInstant(itemID);
if classID == 4 then --Armor
if subclassID == 6 then
slotName = itemSubType;
else
slotName = itemEquipLoc and _G[itemEquipLoc];
end
elseif classID == 2 then --Weapon Type
slotName = itemSubType;
end
if self.showItemName then
local itemName, isLoaded = GetColorizedItemNameFromSource(self.transmogSourceID, itemID)
if isLoaded then
slotName = string.format("%s - %s", slotName, itemName);
else
After(0.2, function()
if self:IsMouseOver() and self:IsVisible() then
TransmogItemButton_OnEnter(self);
end
end);
end
end
end
ExtraDetailFrame:SetEnsembleHeaderText(slotName);
end
end
local function TransmogItemButton_OnLeave(self)
ExtraDetailFrame:SetEnsembleHeaderText();
end
local function SelectProductBySourceID(itemModifiedAppearanceID)
local f = BlizzardFrame.ProductsFrame;
local frozenProductItemInfo = f.FrozenProductContainer:GetItemInfo();
if frozenProductItemInfo and frozenProductItemInfo.itemModifiedAppearanceID == itemModifiedAppearanceID then
f.FrozenProductContainer:SetSelected(true);
return true
end
local scrollContainer = f.ProductsScrollBoxContainer;
local scrollBox = scrollContainer.ScrollBox;
local index, foundElementData = scrollBox:FindByPredicate(function(elementData)
return elementData.itemModifiedAppearanceID == itemModifiedAppearanceID
end);
if foundElementData then
scrollContainer.selectionBehavior:SelectElementData(foundElementData);
scrollBox:ScrollToElementDataIndex(index);
return true
end
return false
end
local function TransmogItemButton_OnClick(self, button)
if button == "LeftButton" then
local playerActor = GetPlayerActor();
if not playerActor then return end;
self.hideItem = not self.hideItem;
local sourceInfo = C_TransmogCollection.GetSourceInfo(self.transmogSourceID);
if not sourceInfo then return end;
local slotID = C_Transmog.GetSlotForInventoryType(sourceInfo.invType);
if self.hideItem then
playerActor:UndressSlot(slotID);
else
playerActor:TryOn(self.transmogSourceID);
end
self:UpdateVisual();
elseif button == "RightButton" then
if self.transmogSourceID then
if SelectProductBySourceID(self.transmogSourceID) then
end
end
end
end
--Pet Ability
local function PetAbilityButton_OnEnter(self)
SetupPetAbilityTooltip(self, self.petAbilityID, self.petAbilityLevel);
end
NarciPerksProgramItemDetailButtonMixin = {};
function NarciPerksProgramItemDetailButtonMixin:OnEnter()
self.Highlight:Show();
if self.onEnterFunc then
self.onEnterFunc(self);
end
end
function NarciPerksProgramItemDetailButtonMixin:OnLeave()
self.Highlight:Hide();
PerksProgramUITooltip:Hide();
if self.onLeaveFunc then
self.onLeaveFunc(self);
end
end
function NarciPerksProgramItemDetailButtonMixin:OnClick(button)
if self.onClickFunc then
self.onClickFunc(self, button);
end
end
function NarciPerksProgramItemDetailButtonMixin:SetTransmogSource(sourceID)
if self.type ~= "transmog" then
self.onEnterFunc = TransmogItemButton_OnEnter;
self.onLeaveFunc = TransmogItemButton_OnLeave;
self.onClickFunc = TransmogItemButton_OnClick;
self.type = "transmog";
end
local icon = C_TransmogCollection.GetSourceIcon(sourceID);
self.Icon:SetTexture(icon);
self:Show();
self.transmogSourceID = sourceID;
self.hideItem = nil;
self:UpdateVisual();
self.GreenCheck:SetShown(C_TransmogCollection.PlayerKnowsSource(sourceID));
end
function NarciPerksProgramItemDetailButtonMixin:SetPetAbilityInfo(abilityID, level)
if self.type ~= "pet" then
self.onEnterFunc = PetAbilityButton_OnEnter;
self.onLeaveFunc = nil;
self.onClickFunc = nil;
self.type = "pet";
end
self.petAbilityID = abilityID;
if abilityID then
local name, icon, typeID = C_PetJournal.GetPetAbilityInfo(abilityID);
self.Icon:SetTexture(icon);
self.petAbilityLevel = level;
self:Show();
end
self.hideItem = nil;
self:UpdateVisual();
self.GreenCheck:Hide();
end
function NarciPerksProgramItemDetailButtonMixin:ClearData()
self.Icon:SetTexture(nil);
self.transmogSourceID = nil;
self.petAbilityID = nil;
self.petAbilityLevel = nil;
self.hideItem = nil;
self:Hide();
end
function NarciPerksProgramItemDetailButtonMixin:UpdateVisual()
if self.hideItem then
self.Icon:SetDesaturated(true);
self.Icon:SetVertexColor(0.72, 0.72, 0.72);
self.RedEye:Hide(); --Always Hidden
else
self.Icon:SetDesaturated(false);
self.Icon:SetVertexColor(1, 1, 1);
self.RedEye:Hide();
end
end
--Small Button (etc. Rotate Left/Right);
NarciPerksProgramSquareButtonMixin = {};
function NarciPerksProgramSquareButtonMixin:OnLoad()
end
function NarciPerksProgramSquareButtonMixin:OnEnter()
if self:IsEnabled() and self.tooltipText then
PerksProgramUITooltip:Hide();
PerksProgramUITooltip:SetOwner(self, "ANCHOR_NONE");
PerksProgramUITooltip:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 2, 2);
PerksProgramUITooltip:SetText(self.tooltipText, 1, 1, 1, true);
PerksProgramUITooltip:Show();
end
end
function NarciPerksProgramSquareButtonMixin:OnLeave()
PerksProgramUITooltip:Hide();
end
function NarciPerksProgramSquareButtonMixin:OnClick()
if self.onClickFunc then
self.onClickFunc(self);
end
end
function NarciPerksProgramSquareButtonMixin:OnMouseDown()
if self:IsEnabled() then
self.Icon:SetPoint("CENTER", self.PushedTexture);
end
end
function NarciPerksProgramSquareButtonMixin:OnMouseUp()
self.Icon:SetPoint("CENTER");
end
function NarciPerksProgramSquareButtonMixin:OnDisable()
self.NormalTexture:SetDesaturated(true);
self.Icon:SetDesaturated(true);
self.NormalTexture:SetVertexColor(0.72, 0.72, 0.72);
self.Icon:SetVertexColor(0.72, 0.72, 0.72);
end
function NarciPerksProgramSquareButtonMixin:OnEnable()
self.NormalTexture:SetDesaturated(false);
self.Icon:SetDesaturated(false);
self.NormalTexture:SetVertexColor(1, 1, 1);
self.Icon:SetVertexColor(1, 1, 1);
end
local ANIMATIONS_MOUNT = {
0, --Stand
4, --Walk
5, --Run
13, --Walk Backwards
94, --Mount Special
548, --Mount Flight Idle
};
local ANIMATIONS_PLAYER_DEFAULT = {
STAND_ANIMATION,
4, --Walk
5, --Run
};
local ANIMATIONS_PLAYER_MELEE_1H = {
STAND_ANIMATION, 4, 5,
26,
};
local ANIMATIONS_PLAYER_MELEE_2H = {
STAND_ANIMATION, 4, 5,
27, 28,
};
local ANIMATIONS_PLAYER_SHIELD = {
STAND_ANIMATION, 4, 5,
26, 1078,
};
local ANIMATIONS_PLAYER_BOW = {
STAND_ANIMATION, 4, 5,
29, 109,
};
local ANIMATIONS_PLAYER_CROSSBOW = {
STAND_ANIMATION, 4, 5,
836, 842,
};
local ANIMATIONS_PLAYER_GUN = {
STAND_ANIMATION, 4, 5,
48, 110,
};
local ANIMATIONS_PLAYER_CASTER = {
STAND_ANIMATION, 4, 5,
51, 52,
};
--[[
local ANIMATIONS_PLAYER = {
0, --Stand
26, --Ready 1H
27, --Ready 2H
28, --Ready 2HL
29, --Ready Bow
48, --Ready Rifle
51, --Ready Spell Directed
52, --Ready Spell Omni
836, --Ready Crossbow
--1026, --Ready Glv
--678, --Monk Offense Ready
--698, --Monk Cast
--860, --Shaman
--896, --Mage
--918, --Warlock
--940, --Druid
--988, --Priest
1078, --Artifact Shield
};
--]]
do
local tinsert = table.insert;
local _, _, classID = UnitClass("player");
if classID == 5 then --Priest
tinsert(ANIMATIONS_PLAYER_CASTER, 988);
elseif classID == 7 then --Shaman
tinsert(ANIMATIONS_PLAYER_CASTER, 860);
elseif classID == 8 then --Mage
tinsert(ANIMATIONS_PLAYER_CASTER, 896);
elseif classID == 9 then --Warlock
tinsert(ANIMATIONS_PLAYER_CASTER, 918);
elseif classID == 10 then --Monk
tinsert(ANIMATIONS_PLAYER_MELEE_1H, 678);
tinsert(ANIMATIONS_PLAYER_MELEE_2H, 678);
tinsert(ANIMATIONS_PLAYER_CASTER, 698);
elseif classID == 11 then --Druid
tinsert(ANIMATIONS_PLAYER_CASTER, 940);
elseif classID == 12 then --DH
tinsert(ANIMATIONS_PLAYER_MELEE_1H, 1026);
end
end
NarciPerksProgramAnimationDropDownMixin = {};
function NarciPerksProgramAnimationDropDownMixin:OnLoad()
AnimationDropDown = self;
self.requireUpdate = true;
self.animationIDs = ANIMATIONS_PLAYER_DEFAULT;
end
function NarciPerksProgramAnimationDropDownMixin:ShowFrame()
self:Build();
self:Show();
end
function NarciPerksProgramAnimationDropDownMixin:UpdateOptions()
local enableDropdown = true;
if SELECTED_DATA then
self.requireUpdate = true;
local categoryID = SELECTED_DATA.perksVendorCategoryID;
self.categoryID = categoryID;
self.perksVendorItemID = SELECTED_DATA.perksVendorItemID;
self.itemID = SELECTED_DATA.itemID;
if categoryID then
if categoryID == 3 then --pet
enableDropdown = false;
self.actor = PerksProgramFrame.ModelSceneContainerFrame.MainModelScene:GetActorByTag("pet");
elseif categoryID == 2 then
self.mode = "mount";
self.actor = PerksProgramFrame.ModelSceneContainerFrame.MainModelScene:GetActorByTag("mount");
else
self.mode = "player";
self.actor = PerksProgramFrame.ModelSceneContainerFrame.playerActor;
end
else
enableDropdown = false;
end
local displayData = SELECTED_DATA.displayData;
if displayData then
self.defaultAnimationKitID = displayData.animationKitID;
if displayData.animationKitID then
self.defaultAnimationID = nil;
else
self.defaultAnimationID = displayData.animation;
end
else
self.defaultAnimationKitID = nil;
self.defaultAnimationID = nil;
end
end
if self.parentButton then
if enableDropdown then
self.parentButton:Enable();
else
self.parentButton:Disable();
end
end
end
local function GetBestAnimationsForItem(mode, itemID)
if mode == "mount" then
return ANIMATIONS_MOUNT
else
if itemID then
local _, _, _, itemEquipLoc, _, classID, subclassID = GetItemInfoInstant(itemID);
if classID == 4 then
if subclassID == 6 then
return ANIMATIONS_PLAYER_SHIELD
else
return ANIMATIONS_PLAYER_DEFAULT
end
elseif classID == 2 then
if subclassID == 2 then
return ANIMATIONS_PLAYER_BOW
elseif subclassID == 3 then
return ANIMATIONS_PLAYER_GUN
elseif subclassID == 18 then
return ANIMATIONS_PLAYER_CROSSBOW
else
if itemEquipLoc == "INVTYPE_2HWEAPON" then
return ANIMATIONS_PLAYER_MELEE_2H
else
return ANIMATIONS_PLAYER_MELEE_1H
end
end
else
return ANIMATIONS_PLAYER_DEFAULT
end
else
return ANIMATIONS_PLAYER_DEFAULT
end
end
end
function NarciPerksProgramAnimationDropDownMixin:Build()
if not self.isLoaded then
self.isLoaded = true;
NarciAPI.NineSliceUtil.SetUpBorder(self.BackgroundFrame, "genericChamferedBorder", nil, 0.25, 0.25, 0.25, 1, 7);
NarciAPI.NineSliceUtil.SetUpBackdrop(self.BackgroundFrame, "genericChamferedBackground", nil, 0, 0, 0, 0.9, -8);
self.buttons = {};
self.getNameFunc = NarciAnimationInfo.GetOfficialName;
end
if self.requireUpdate then
self.requireUpdate = nil;
self.animationIDs = GetBestAnimationsForItem(self.mode, self.itemID);
local paddingV = 8;
local buttonHeight = 24;
local numButtons = #self.animationIDs;
local defaultAnimationID = self.defaultAnimationID;
local defaultOption = defaultAnimationID or self.defaultAnimationKitID;
if self.mode == "mount" then
self.defaultAnimationKitID = MOUNT_SPECIAL_ANIM_KIT;
defaultOption = MOUNT_SPECIAL_ANIM_KIT;
defaultAnimationID = nil;
end
if defaultAnimationID then
for i = 1, #self.animationIDs do
if self.animationIDs[i] == defaultAnimationID then
defaultOption = nil;
break
end
end
end
if defaultOption then --Add a "Default" button if the default animation isn't on our animation list
numButtons = numButtons + 1;
end
local button;
local maxNumberWidth = 0;
local maxNameWidth = 0;
local numberWidth, nameWidth;
numButtons = numButtons + 1; --We use the first button as a checkbox/toggle
local offsetY = paddingV;
local animationButtonIndex = 0;
self.indexedButtons = {};
for i = 1, numButtons do
if not self.buttons[i] then
self.buttons[i] = CreateFrame("Button", nil, self, "NarciPerksProgramDropDownButtonTemplate");
end
button = self.buttons[i];
button:ClearAllPoints();
button:SetPoint("TOPLEFT", self, "TOPLEFT", 0, -offsetY);
if i == 1 then --Modify Default Pose
numberWidth, nameWidth = button:SetModelSetupToggle();
local dividerHeight = 12;
offsetY = offsetY + buttonHeight;
if not self.Divider then
self.Divider = self:CreateTexture(nil, "OVERLAY");
self.Divider:SetPoint("TOPLEFT", self, "TOPLEFT", 0, -(offsetY + 0.5*dividerHeight));
self.Divider:SetPoint("RIGHT", self, "RIGHT", 0, 0);
self.Divider:SetColorTexture(0.2, 0.2, 0.2);
end
local pixel = NarciAPI.GetPixelForWidget(self, 1);
self.Divider:SetHeight(pixel);
offsetY = offsetY + dividerHeight;
else
animationButtonIndex = animationButtonIndex + 1;
self.indexedButtons[animationButtonIndex] = button;
button.index = animationButtonIndex;
if defaultOption and i == numButtons then
if self.defaultAnimationKitID then
numberWidth, nameWidth = button:SetAnimationOption(L["Default Animation"], self.defaultAnimationKitID, true);
else
numberWidth, nameWidth = button:SetAnimationOption(L["Default Animation"], defaultAnimationID);
end
else
numberWidth, nameWidth = button:SetAnimationOption(self.getNameFunc(self.animationIDs[i-1]), self.animationIDs[i-1]);
end
offsetY = offsetY + buttonHeight;
end
if numberWidth > maxNumberWidth then
maxNumberWidth = numberWidth;
end
if nameWidth > maxNameWidth then
maxNameWidth = nameWidth;
end
button:SetButtonFontColor(1);
end
self.maxIndex = animationButtonIndex;
maxNumberWidth = math.floor(maxNumberWidth + 0.5);
local buttonWidth = math.floor(12 + maxNumberWidth + 12 + maxNameWidth + 12 + 0.5);
if buttonWidth < 192 then
buttonWidth = 192;
end
for i = 1, numButtons do
self.buttons[i]:SetElementSizes(maxNumberWidth, buttonWidth);
self.buttons[i]:Show();
end
for i = numButtons + 1, #self.buttons do
self.buttons[i]:Hide();
end
self:SetWidth(buttonWidth);
self:SetHeight(offsetY + paddingV);
if CHANGE_POSE then
self:SelectAnimationByIndex(1);
else
if defaultOption then
self:SelectButton(self.buttons[numButtons]);
else
self:SelectButtonByAnimID(defaultAnimationID);
end
end
end
end
function NarciPerksProgramAnimationDropDownMixin:SetParentButton(button)
self.parentButton = button;
self:ClearAllPoints();
self:SetPoint("BOTTOMLEFT", button, "TOPLEFT", 4, 4);
self:SetParent(button);
end
local function AnimationButton_OnMouseWheel(self, delta)
AnimationDropDown:OnMouseWheel(delta);
end
function NarciPerksProgramAnimationDropDownMixin:OnShow()
self:RegisterEvent("GLOBAL_MOUSE_DOWN");
if self.parentButton then
self.parentButton:SetScript("OnMouseWheel", AnimationButton_OnMouseWheel);
end
end
function NarciPerksProgramAnimationDropDownMixin:OnHide()
self:Hide();
self:UnregisterEvent("GLOBAL_MOUSE_DOWN");
if self.parentButton then
self.parentButton:SetScript("OnMouseWheel", nil);
end
end
function NarciPerksProgramAnimationDropDownMixin:OnEvent()
if not (self:IsMouseOver() or (self.parentButton and self.parentButton:IsMouseOver()) ) then
self:Hide();
end
end
function NarciPerksProgramAnimationDropDownMixin:HighlightButton(button)
self.ButtonHighlight:ClearAllPoints();
if button then
self.ButtonHighlight:SetPoint("TOPLEFT", button, "TOPLEFT", 2, 0);
self.ButtonHighlight:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 0);
self.ButtonHighlight:Show();
else
self.ButtonHighlight:Hide();
end
end
local function AnimationDropDown_PlayAnimation(actor, button)
if not actor then return end;
actor:StopAnimationKit();
actor:SetAnimationBlendOperation(1); --LE_MODEL_BLEND_OPERATION_ANIM
if button.animationKitID then
actor:PlayAnimationKit(button.animationKitID, true);
elseif button.animationID then
actor:SetAnimation(button.animationID);
end
end
function NarciPerksProgramAnimationDropDownMixin:SelectButton(button, click)
if self.buttons then
for i, b in ipairs(self.buttons) do
if b == button then
b.isSelected = true;
b:SetButtonFontColor(3);
elseif b.isSelected then
b.isSelected = nil;
b:SetButtonFontColor(1);
end
end
end
self.selectedButtonIndex = button.index;
self:HighlightButton();
if click then
AnimationDropDown_PlayAnimation(self.actor, button);
end
end
function NarciPerksProgramAnimationDropDownMixin:SelectAnimationByIndex(index, click)
if self.indexedButtons then
for i, b in ipairs(self.indexedButtons) do
if i == index then
b.isSelected = true;
b:SetButtonFontColor(3);
if click then
AnimationDropDown_PlayAnimation(self.actor, b);
end
elseif b.isSelected then
b.isSelected = nil;
b:SetButtonFontColor(1);
end
end
end
self.selectedButtonIndex = index;
end
function NarciPerksProgramAnimationDropDownMixin:SelectButtonByAnimID(animID, click)
if self.buttons then
for i, b in ipairs(self.buttons) do
if b.animationID == animID then
b.isSelected = true;
b:SetButtonFontColor(3);
self.selectedButtonIndex = b.index;
if click then
AnimationDropDown_PlayAnimation(self.actor, b);
end
elseif b.isSelected then
b.isSelected = nil;
b:SetButtonFontColor(1);
end
end
end
end
function NarciPerksProgramAnimationDropDownMixin:OnMouseWheel(delta)
if not self.selectedButtonIndex then
self.selectedButtonIndex = 0;
end
if not self.maxIndex then
self.maxIndex = 1;
end
if delta < 0 then
self.selectedButtonIndex = self.selectedButtonIndex + 1;
if self.selectedButtonIndex > self.maxIndex then
self.selectedButtonIndex = 1;
end
else
self.selectedButtonIndex = self.selectedButtonIndex - 1;
if self.selectedButtonIndex < 1 then
self.selectedButtonIndex = self.maxIndex;
end
end
self:SelectAnimationByIndex(self.selectedButtonIndex, true);
end
NarciPerksProgramDropDownButtonMixin = {};
function NarciPerksProgramDropDownButtonMixin:OnMouseDown()
self.OptionNumber:SetPoint("LEFT", self, "LEFT", 13, 0);
end
function NarciPerksProgramDropDownButtonMixin:OnMouseUp()
self.OptionNumber:SetPoint("LEFT", self, "LEFT", 12, 0);
end
function NarciPerksProgramDropDownButtonMixin:OnEnter()
if not self.isSelected then
AnimationDropDown:HighlightButton(self);
self:SetButtonFontColor(2);
else
AnimationDropDown:HighlightButton();
end
if self.tooltip then
local tooltip = PerksProgramUITooltip;
tooltip:SetOwner(self, "ANCHOR_RIGHT");
tooltip:SetText(self.OptionName:GetText(), 1, 1, 1);
tooltip:AddLine(self.tooltip, 1, 0.82, 0, true);
tooltip:Show();
end
end
function NarciPerksProgramDropDownButtonMixin:OnLeave()
AnimationDropDown:HighlightButton();
PerksProgramUITooltip:Hide();
if not self.isSelected then
self:SetButtonFontColor(1);
end
end
function NarciPerksProgramDropDownButtonMixin:SetButtonFontColor(colorIndex)
SetButtonFontColor(self.OptionName, colorIndex);
SetButtonFontColor(self.OptionNumber, colorIndex);
end
function NarciPerksProgramDropDownButtonMixin:SetAnimationOption(name, id, isAnimKit)
self.onClickFunc = self.OnClick_Animation;
self.OptionName:SetText(name);
self.OptionNumber:SetWidth(0);
local nameWidth = self.OptionName:GetWrappedWidth()
local numberWidth;
if id and not isAnimKit then
self.OptionNumber:SetText(id);
self.OptionNumber:Show();
numberWidth = self.OptionNumber:GetWrappedWidth();
else
self.OptionNumber:SetText("--");
self.OptionNumber:Show();
numberWidth = 0;
end
if isAnimKit then
self.animationKitID = id;
self.animationID = nil;
else
self.animationKitID = nil;
self.animationID = id;
end
return numberWidth, nameWidth;
end
local function UpdateModelSetupCheckbox(dropdownButton)
if dropdownButton.Checkbox then
if CHANGE_POSE then
dropdownButton.Checkbox:SetTexCoord(0, 0.5, 0, 1);
else
dropdownButton.Checkbox:SetTexCoord(0.5, 1, 0, 1);
end
end
end
function NarciPerksProgramDropDownButtonMixin:SetModelSetupToggle()
self.onClickFunc = self.OnClick_ModelSetupToggle;
self.OptionName:SetText(L["Modify Default Pose"]);
self.OptionNumber:Hide();
local numberWidth = 0;
local nameWidth = self.OptionName:GetWrappedWidth()
if not self.Checkbox then
self.Checkbox = self:CreateTexture(nil, "OVERLAY");
self.Checkbox:SetPoint("LEFT", self, "LEFT", 6, 0);
self.Checkbox:SetSize(40, 40);
self.Checkbox:SetTexture("Interface/AddOns/Narcissus/Art/Modules/PerksProgram/TwoStateCheckbox");
end
UpdateModelSetupCheckbox(self);
self.tooltip = L["Modify Default Pose Tooltip"];
return numberWidth, nameWidth
end
function NarciPerksProgramDropDownButtonMixin:SetElementSizes(numberWidth, buttonWidth)
if numberWidth > 0 then
self.OptionNumber:SetWidth(numberWidth);
end
self:SetWidth(buttonWidth);
end
function NarciPerksProgramDropDownButtonMixin:OnClick()
if self.onClickFunc then
self.onClickFunc(self);
end
end
function NarciPerksProgramDropDownButtonMixin:OnClick_Animation()
AnimationDropDown:SelectButton(self, true);
end
function NarciPerksProgramDropDownButtonMixin:OnClick_ModelSetupToggle()
CHANGE_POSE = not CHANGE_POSE;
UpdateModelSetupCheckbox(self);
NarcissusDB.TradingPostChangePost = CHANGE_POSE;
if SELECTED_DATA then
UpdateProductModelAnimation(SELECTED_DATA, true);
end
end
--[[
if true then
local f = CreateFrame("Frame");
f:RegisterEvent("PERKS_PROGRAM_OPEN");
f:RegisterEvent("PERKS_PROGRAM_DATA_REFRESH");
f:SetScript("OnEvent", function(self, event, ...)
print(event, ...)
if event == "PERKS_PROGRAM_OPEN" then
After(0.5, function()
PerksProgramFrame:SetPropagateKeyboardInput(true);
--PerksProgramFrame:SetToplevel(false);
--PerksProgramFrame:SetFrameStrata("LOW");
SetUIVisibility(true)
end);
end
end);
end
function InjectVendorItemIDs()
LoadAddOn("Blizzard_PerksProgram")
ShowUIPanel(PerksProgramFrame);
PerksProgramFrame:SetPropagateKeyboardInput(true);
BlizzardFrame.vendorItemIDs = DataProvider:GetCurrentMonthItems();
BlizzardFrame.ProductsFrame:UpdateProducts();
print("Injected")
end
--]]