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.

4960 lines
138 KiB

local _, addon = ...
local TransitionAPI = addon.TransitionAPI;
local SetModelLight = addon.TransitionAPI.SetModelLight;
local GetModelLight = addon.TransitionAPI.GetModelLight;
local SetGradient = addon.TransitionAPI.SetGradient;
local SetModelByUnit = addon.TransitionAPI.SetModelByUnit;
local SetModelCameraPosition = addon.TransitionAPI.SetCameraPosition;
local CopyTable = addon.CopyTable;
local GetAlternateFormInfo = C_PlayerInfo.GetAlternateFormInfo or HasAlternateForm;
local Narci = Narci;
local L = Narci.L;
local pi = math.pi;
local sin = math.sin;
local cos = math.cos;
local atan2 = math.atan2;
local sqrt = math.sqrt;
local FadeFrame = NarciFadeUI.Fade;
local FadeIn = NarciFadeUI.FadeIn;
local After = C_Timer.After;
local SmartSetActorName = NarciAPI.SmartSetActorName;
local NarciAnimationInfo = NarciAnimationInfo;
local NarciSpellVisualBrowser = NarciSpellVisualBrowser;
local GetCursorPosition = GetCursorPosition;
local IsAltKeyDown = IsAltKeyDown;
local Screenshot = Screenshot; --This is an API: screen capture
local IsMouseButtonDown = IsMouseButtonDown;
local _G = _G;
local VIRTUAL_ACTOR = L["Virtual Actor"];
local WidgetTooltip = NarciTooltip;
local SettingFrame, BasicPanel;
local FullSceenChromaKey, FullScreenAlphaChannel;
local PrimaryPlayerModel, ActorPanel; --PrimaryPlayerModel
local AnimationIDEditBox, VariationButton;
local OutfitToggle;
local CaptureButton
local ModelContainer;
-----------------------------------
local defaultZ = -0.275;
local defaultY = 0.4;
local startY = 2.5;
local endFacing = -3.14/8;
local maxAnimationID = NarciConstants.Animation.MaxAnimationID or 1499; --Auto-updated
local NUM_MAX_ACTORS = 8;
local IndexButtonPosition = {
1, 2, 3, 4, 5, 6, 7, 8
};
local HIT_RECT_OFFSET = 0;
local function HighlightButton(button, state, sound)
if state then
button:LockHighlight();
button.Label:SetTextColor(0.88, 0.88, 0.88);
if sound then
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
end
else
button:UnlockHighlight();
button.Label:SetTextColor(0.65, 0.65, 0.65);
if sound then
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF);
end
end
end
local LINK_SCALE = false;
local LINK_LIGHT = true;
local LOOP_ANIMATION = false;
local GLOBAL_CAMERA_PITCH = pi/2;
local ModelSettings = {
["Generic"] = { panMaxLeft = -4, panMaxRight = 3, panMaxTop = 1.2, panMaxBottom = -1.6, panValue = 40 },
}
local TranslateValue_Male = {
--[raceID] = {ZoomValue(1.Bust 2.FullBody), defaultY, defaultZ},
[0] = {[1] = {0.05, 0.4, -0.275}, --Default Value
[2] = {0.05, 0.4, -0.275}},
[1] = {[1] = {0, 0.95, -0.36},
[2] = {-0.3, 1.21, -0.09}}, --1 Human √
[2] = {[1] = {-0.1, 1.33, -0.65},
[2] = {-0.5, 1.67, -0.34}}, --2 Orc √ -0.1 -0.5
[3] = {[1] = {0.05, 0.633, -0.06},
[2] = {-0.4, 0.93, 0.16}}, --3 Dwarf √
[4] = {[1] = {0.1, 0.98, -0.68},
[2] = {-0.2, 1.33, -0.25}}, --4 NE √
[5] = {[1] = {0.1, 0.83, -0.31},
[2] = {-0.3, 1.21, -0.05}}, --5 UD √
[6] = {[1] = {-0.1, 1.4, -1},
[2] = {-0.4, 1.87, -0.58}}, --6 Tauren Male √
[7] = {[1] = {0.05, 0.485, 0.22},
[2] = {-0.6, 0.78, 0.332}}, --7 Gnome √
[8] = {[1] = {-0.2, 1, -0.58},
[2] = {-0.6, 1.33, -0.3}}, --8 Troll √
[9] = {[1] = {0, 0.54, 0.12},
[2] = {-0.5, 0.82, 0.26}}, --9 Goblin √
[10] = {[1] = {0.2, 0.86, -0.5},
[2] = {-0.3, 1.3, -0.09}}, --10 BloodElf Male √
[11] = {[1] = {-0.1, 1.28, -0.72},
[2] = {-0.5, 1.73, -0.39}}, --11 Goat Male √
[22] = {[1] = {-0.1, 0.92, -0.58},
[2] = {-0.55, 1.44, -0.26}}, --22 Worgen Wolf form √
[24] = {[1] = {0, 1.07, -0.62},
[2] = {-0.3, 1.54, -0.31}}, --24 Pandaren Male √
[27] = {[1] = {0.1, 0.46, -0.35},
[2] = {-0.3, 1.41, -0.32}}, --27 Nightborne
[28] = {[1] = {0.05, 0, -0.09},
[2] = {-0.6, 0.3, -0.175}}, --28 Tauren Male √
[31] = {[1] = {0.1, 0.61, -0.4},
[2] = {-0.3, 1.71, -0.48}}, --31 Zandalari
[32] = {[1] = {0.1, 0.97, -0.8},
[2] = {-0.4, 1.48, -0.36}}, --32 Kul'Tiran √
[36] = {[1] = {0, 1.17, -0.55},
[2] = {-0.3, 1.52, -0.28}}, --36 Mag'har
[35] = {[1] = {0.3, 0.73, 0.111},
[2] = {0, 0.95, 0.2375}}, --35 Vulpera √
[52] = {[1] = {-0.1, 1.02, -0.57},
[2] = {-0.8, 2.13, -0.55}}, --35 Dracthyr √
[84] = {[1] = {-0.1, 1.02, -0.57},
[2] = {-0.6, 1.24, 0.05}}, --84/85 Earthen √
};
local TranslateValue_Female = {
--[raceID] = {ZoomValue, defaultY, defaultZ},
[0] = {[1] = {0.05, 0.4, -0.275}, --Default Value
[2] = {0.05, 0.4, -0.275}},
[1] = {[1] = {0.1, 0.77, -0.355},
[2] = {-0.3, 1.18, 0}}, --1 Human √
[2] = {[1] = {0.1, 0.88, -0.46},
[2] = {-0.3, 1.29, -0.138}}, --2 Orc √
[3] = {[1] = {0.0, 0.71, -0.04},
[2] = {-0.3, 0.93, 0.167}}, --3 Dwarf √
[4] = {[1] = {0.2, 0.28, -0.28},
[2] = {-0.3, 1.28, -0.22}}, --4 NE √
[5] = {[1] = {0.2, 0.708, -0.332},
[2] = {-0.3, 1.06, -0.00}}, --5 UD
[6] = {[1] = {0.1, 1.121, -0.91},
[2] = {-0.4, 1.7, -0.416}}, --6 Tauren Female √
[7] = {[1] = {0.05, 0.56, 0.27},
[2] = {-0.4, 0.73, 0.37}}, --7 Gnome √
[8] = {[1] = {0.1, 0.89, -0.73},
[2] = {-0.4, 1.38, -0.23}}, --8 Troll √
[9] = {[1] = {0, 0.60, 0.07},
[2] = {-0.5, 0.85, 0.236}}, --9 Goblin √
[10] = {[1] = {0.2, 0.71, -0.38},
[2] = {-0.3, 1.2, 0}}, --10 BloodElf Female √
[11] = {[1] = {0.2, 0.8, -0.73},
[2] = {-0.3, 1.33, -0.23}}, --11 Goat Female √
[22] = {[1] = {-0.1, 0.955, -0.773},
[2] = {-0.6, 1.455, -0.27}}, --22 Worgen Wolf form √
[24] = {[1] = {-0.1, 1, -0.54},
[2] = {-0.5, 1.37, -0.15}}, --24 Pandaren Female √
[27] = {[1] = {0.1, 0.45, -0.35},
[2] = {-0.3, 1.33, -0.19}}, --27 Nightborne
[31] = {[1] = {0.2, 0.5, -0.454},
[2] = {-0.4, 1.73, -0.427}}, --31 Zandalari
[32] = {[1] = {0.1, 0.88, -0.75},
[2] = {-0.5, 1.37, -0.24}}, --32 Kul'Tiran √
[36] = {[1] = {0.1, 0.88, -0.46},
[2] = {-0.3, 1.29, -0.138}}, --2 Orc √
[35] = {[1] = {0.3, 0.73, 0.111},
[2] = {-0.6, 0.98, 0.25}}, --35 Vulpera √
[84] = {[1] = {-0.1, 1.02, -0.57},
[2] = {-0.4, 1.15, 0.00}}, --84/85 Earthen √
}
TranslateValue_Female[36] = TranslateValue_Female[2];
TranslateValue_Male[70] = TranslateValue_Male[52];
TranslateValue_Female[52] = TranslateValue_Male[52];
TranslateValue_Female[70] = TranslateValue_Male[52];
local function ReAssignRaceID(raceID, custom)
if raceID == 30 then --Lightforged
raceID = 11;
elseif raceID == 36 then --Mag'har Orc
--raceID = 2;
elseif raceID == 34 then --DarkIron
raceID = 3;
elseif raceID == 22 then --WorgenXgenderID
local _, inAlternateForm = GetAlternateFormInfo();
if inAlternateForm and not custom then --Human form is Worgen's alternate form
raceID = 1;
end
elseif raceID == 25 or raceID == 26 then --Pandaren A|H
raceID = 24;
elseif raceID == 28 then --Hightmountain
raceID = 6;
elseif raceID == 29 then
raceID = 10;
elseif raceID == 37 then --Mechagnome
raceID = 7;
elseif raceID == 52 or raceID == 70 then --dracthyr visage
local _, inAlternateForm = GetAlternateFormInfo();
if inAlternateForm then --Human form is Worgen's alternate form
raceID = 10; --blood elf
end
elseif raceID == 85 then --Earthen
raceID = 84;
end
return raceID;
end
local TranslateValue;
local function AssignModelPositionTable(race, gender)
local _, _, raceID = UnitRace("player");
raceID = race or raceID;
raceID = ReAssignRaceID(raceID);
local genderID = gender or UnitSex("player"); --2 Male 3 Female
if genderID == 2 then
TranslateValue = TranslateValue_Male[raceID];
else
TranslateValue = TranslateValue_Female[raceID];
end
if not TranslateValue then
print("Narcissus: AssignModelPositionTable Failed Unrecognized Race: "..raceID);
TranslateValue = TranslateValue_Male[1];
end
end
-----------------------------------
local function outSine(t, b, c, d)
return c * sin(t / d * (pi / 2)) + b
end
local function outQuad(t, b, c, d)
t = t / d
return -c * t * (t - 2) + b
end
-----------------------------------
local ACTIVE_MODEL_INDEX = 1;
local ModelFrames = {}; --active models (max: 8);
local ModelPool = {}; --all models created, including DressUpModel and CinematicModel (max: 8*2);
local PlayerInfo = {};
local function SetGenderIcon(genderID)
--"SetCustomRace" removed in 10.1.5
local button = Narci_GenderButton;
if genderID == 3 then
--female
button.Icon:SetTexCoord(0.5, 1, 0, 0.5);
button.Icon2:SetTexCoord(0.5, 1, 0, 0.5);
button.Highlight:SetTexCoord(0.5, 1, 0.5, 1);
elseif genderID == 2 then
button.Icon:SetTexCoord(0, 0.5, 0, 0.5);
button.Icon2:SetTexCoord(0, 0.5, 0, 0.5);
button.Highlight:SetTexCoord(0, 0.5, 0.5, 1);
end
end
local function GetUnitRaceIDAndSex(unit)
unit = unit or "player";
local _, _, raceID = UnitRace(unit);
local gender = UnitSex(unit);
return raceID or 1, gender
end
local function InitializePlayerInfo(index, unit)
local unit = unit or "player";
local name = UnitName(unit);
local _, className = UnitClass(unit);
local race, gender = GetUnitRaceIDAndSex(unit);
PlayerInfo[index] = PlayerInfo[index] or {};
PlayerInfo[index].raceID_Original, PlayerInfo[index].gender_Original = race, gender;
PlayerInfo[index].raceID = PlayerInfo[index].raceID_Original;
PlayerInfo[index].gender = PlayerInfo[index].gender_Original;
PlayerInfo[index].name = name;
PlayerInfo[index].class = className;
--SetGenderIcon(PlayerInfo[index].gender_Original);
local r, g, b = GetClassColor(className);
local fontstring = ActorPanel.ExtraPanel.buttons[index].Label; --name tooltip
SmartSetActorName(fontstring, name);
fontstring:SetTextColor(r, g, b);
return race, gender;
end
local function RestorePlayerInfo(index)
if not PlayerInfo[index] then return; end;
PlayerInfo[index].raceID = PlayerInfo[index].raceID_Original;
PlayerInfo[index].gender = PlayerInfo[index].gender_Original;
--SetGenderIcon(PlayerInfo[index].gender_Original);
end
local function UpdateActorName(index)
local str = ActorPanel.ActorButton.ActorName;
local className = PlayerInfo[index].class;
local r, g, b = GetClassColor(className);
if className == "DEATHKNIGHT" or className == "DEMONHUNTER" or className == "SHAMAN" then
r, g, b = r + 0.05, g + 0.05, b + 0.05;
end
SmartSetActorName(str, PlayerInfo[index].name or "Unnamed");
str:SetTextColor(r, g, b);
end
local function ResetModelPosition(model)
model:SetPosition(0, 0, 0);
end
local function UpdateGroundShadowOption()
local button = Narci_GroundShadowToggle;
local model = ModelFrames[ACTIVE_MODEL_INDEX];
local shadowFrame = model.GroundShadow;
local state = shadowFrame:IsShown();
HighlightButton(button, state, true);
Narci_GroundShadowOption:ReAnchor(model, shadowFrame.Option);
end
-------------------------
--Model Control Buttons--
-------------------------
local function DisablePlayButton()
local playButton = NarciModelControl_PlayAnimationButton;
local animationSlider = NarciModelControl_AnimationSlider;
playButton.isOn = false;
playButton.Highlight:Hide();
animationSlider:Show();
local pauseButton = NarciModelControl_PauseAnimationButton;
pauseButton.isOn = true;
pauseButton.Highlight:Show();
end
local function DisablePauseButton()
local pauseButton = NarciModelControl_PauseAnimationButton;
local animationSlider = NarciModelControl_AnimationSlider;
pauseButton.isOn = false;
pauseButton.Highlight:Hide();
if animationSlider:IsShown() then
animationSlider.animOut:Play();
end
local playButton = NarciModelControl_PlayAnimationButton;
playButton.isOn = true;
playButton.Highlight:Show();
end
local function Narci_CharacterModelFrame_OnShow(self)
--xmogMode -- 0 off 1 "Texts Only" 2 "Texts & Model"
if self.xmogMode == 2 then
--NarciModel_RightGradient:Show();
else
NarciModel_RightGradient:Hide();
end
if not SettingFrame:IsShown() then
SettingFrame:FadeIn(0.5, 1);
end
end
function Narci_CharcaterModelFrame_OnHide(self)
if ( self.panning ) then
self.panning = false;
end
self.mouseDown = false;
end
local function rotateTexture(tex, Degree)
local ag = tex.ag;
if not ag then
ag = tex:CreateAnimationGroup();
end
local a1 = ag.a1;
if not a1 then
a1 = ag:CreateAnimation("Rotation");
ag.a1 = a1;
end
ag:Stop();
a1:SetRadians(Degree);
a1:SetOrigin("CENTER",0 ,0);
a1:SetOrder(1);
a1:SetDuration(0);
local a2 = ag.a2;
if not a2 then
a2 = ag:CreateAnimation("Rotation");
ag.a2 = a2;
end
a2:SetRadians(0);
a2:SetOrigin("CENTER",0 ,0);
a2:SetOrder(2);
a2:SetDuration(1);
ag:Play();
ag:Pause();
tex.ag = ag;
end
local RGB2HSV = NarciAPI.RGB2HSV;
local RGBRatio2HSV = NarciAPI.RGBRatio2HSV;
local HSV2RGB = NarciAPI.HSV2RGB;
local LightControl = {};
addon.PhotoModeLightController = LightControl;
LightControl.ambientMode = false;
LightControl.angleZ = pi/4;
LightControl.angleXY = -3*pi/4;
LightControl.targetModelIndex = 1;
function LightControl:SetLightWidgetFromActiveModel()
local model = ModelFrames[ACTIVE_MODEL_INDEX];
local _, _, dirX, dirY, dirZ, ambIntensity, ambR, ambG, ambB, dirIntensity, dirR, dirG, dirB = GetModelLight(model);
local hypotenuse = sqrt(dirX*dirX + dirY*dirY);
local angleZ = -atan2(dirZ, hypotenuse);
local angleXY = - pi - atan2(dirX, dirY);
local r = self.radius;
local button1 = self.parentButton1;
local button2 = self.parentButton2;
local x1, y1 = r*cos(angleZ), r*sin(angleZ);
local x2, y2 = r*cos(angleXY), r*sin(angleXY);
button1:SetPoint("CENTER", x1, y1);
button1.Tex:SetRotation(angleZ);
button1.Highlight:SetRotation(angleZ);
BasicPanel.SideView.LightColor:SetRotation(angleZ);
button2:SetPoint("CENTER", x2, y2);
button2.Tex:SetRotation(angleXY);
button2.Highlight:SetRotation(angleXY);
BasicPanel.TopView.LightColor:SetRotation(angleXY);
local h, s, v;
if self.ambientMode then
h, s, v = RGBRatio2HSV(ambR, ambG, ambB);
else
h, s, v = RGBRatio2HSV(dirR, dirG, dirB);
end
NarciModelControl_HueSlider:SetValue(h);
NarciModelControl_SaturationSlider:SetValue(s);
NarciModelControl_BrightnessSlider:SetValue(v);
BasicPanel.TopView.AmbientColor:SetColorTexture(ambR, ambG, ambB, 0.6);
BasicPanel.SideView.AmbientColor:SetColorTexture(ambR, ambG, ambB, 0.6);
BasicPanel.TopView.LightColor:SetVertexColor(dirR, dirG, dirB, 0.6);
BasicPanel.SideView.LightColor:SetVertexColor(dirR, dirG, dirB, 0.6);
end
function LightControl:CopyLightToNewModel(newModel)
if self.targetModelIndex and ModelFrames[self.targetModelIndex] then
TransitionAPI.SetModelLightFromModel(newModel, ModelFrames[self.targetModelIndex]);
end
end
function LightControl:UpdateModel()
local phi = pi/2-(self.angleZ);
local rX = sin(phi)*sin(self.angleXY);
local rY = -sin(phi)*cos(self.angleXY);
local rZ = -cos(phi);
--print(rX, rY, rZ);
local _, _, _, _, _, ambIntensity, ambR, ambG, ambB, dirIntensity, dirR, dirG, dirB = GetModelLight(ModelFrames[ACTIVE_MODEL_INDEX]);
if LINK_LIGHT then
for i = 1, #ModelFrames do
SetModelLight(ModelFrames[i], true, false, rX, rY, rZ, ambIntensity, ambR, ambG, ambB, dirIntensity, dirR, dirG, dirB);
end
else
SetModelLight(ModelFrames[ACTIVE_MODEL_INDEX], true, false, rX, rY, rZ, ambIntensity, ambR, ambG, ambB, dirIntensity, dirR, dirG, dirB);
end
--[[
local ModelScene = DaedalusStudio.PrimaryModelScene;
ModelScene:SetLightDirection(rX, rY, rZ);
ModelScene:SetLightDiffuseColor(dirR, dirG, dirB);
ModelScene:SetLightAmbientColor(ambR, ambG, ambB);
print(rX, rY, rZ, dirR, dirG, dirB, ambR, ambG, ambB);
--]]
end
function LightControl:SetDirection(radian, heightRatio)
local r = self.radius;
local button1 = self.parentButton1;
local button2 = self.parentButton2;
if not r then return end
local x2, y2 = r*cos(radian), r*sin(radian);
button2:SetPoint("CENTER", x2, y2);
button2.Tex:SetRotation(radian);
button2.Highlight:SetRotation(radian);
BasicPanel.TopView.LightColor:SetRotation(radian);
self.angleXY = radian;
self:UpdateModel();
end
----------------------------------------------------------------------
--Fix Weapon Missing Issue
local WeaponUpdator = {};
WeaponUpdator.GetInspectTransmogInfo = C_TransmogCollection.GetInspectSources or C_TransmogCollection.GetInspectItemTransmogInfoList; --API changed in 9.1.0
function WeaponUpdator:GetPlayerWeapons(model)
model = model or PrimaryPlayerModel;
if not model or not model.TryOn then return end;
local transmogLocation = CreateFromMixins(TransmogLocationMixin);
local transmogType = 0;
local modification = 0;
local baseSourceID, baseVisualID, appliedSourceID, appliedVisualID;
for slotID = 16, 17 do
transmogLocation:Set(slotID, transmogType, modification);
baseSourceID, baseVisualID, appliedSourceID, appliedVisualID = C_Transmog.GetSlotVisualInfo(transmogLocation);
if appliedSourceID == 0 then
model:UndressSlot(slotID);
else
if slotID == 16 then
model:TryOn(appliedSourceID, "MAINHANDSLOT");
else
model:TryOn(appliedSourceID, "SECONDARYHANDSLOT");
end
end
--print(slotID..": "..appliedSourceID)
end
end
function WeaponUpdator:GetTargetWeapons(unit)
local model = ModelFrames[ACTIVE_MODEL_INDEX];
if false and UnitIsUnit(unit, "player") then
WeaponUpdator:GetPlayerWeapons(model);
else
if model and CanInspect(unit) then
self:SetListener(true, unit);
NotifyInspect(unit);
end
end
end
function WeaponUpdator:SetListener(state, unit)
if state then
if not self.queue then
self.queue = {};
end
if not self.eventListener then
self.eventListener = CreateFrame("Frame");
self.eventListener:SetScript("OnEvent", function(f, event, inspecteeGUID)
if not self.pauseUpdate then
self.pauseUpdate = true;
self:ProcessInspect(inspecteeGUID);
end
end);
end
local guid = UnitGUID(unit);
self.queue[guid] = ModelFrames[ACTIVE_MODEL_INDEX];
self.eventListener:RegisterEvent("INSPECT_READY");
else
if self.eventListener then
wipe(self.queue);
self.eventListener:UnregisterEvent("INSPECT_READY");
ClearInspectPlayer();
end
end
end
function WeaponUpdator:ProcessInspect(inspecteeGUID)
local model = self.queue[inspecteeGUID];
if model then
local transmogInfoList, mainHandEnchant, offHandEnchant = self.GetInspectTransmogInfo();
if not model.equippedWeapons then
model.equippedWeapons = {};
end
if model.SetItemTransmogInfo then
local hand = 0;
local transmogInfo;
local mainHandInfo, offHandInfo;
for slotID = 16, 17 do
hand = hand + 1;
transmogInfo = transmogInfoList[slotID];
if transmogInfo then
--[[
local currentInfo = model:GetItemTransmogInfo(slotID);
if not transmogInfo:IsEqual(currentInfo) then
model:SetItemTransmogInfo(transmogInfo, slotID, slotID ~= 16);
end
--]]
model.equippedWeapons[hand] = transmogInfo.appearanceID;
local currentInfo = model:GetItemTransmogInfo(slotID);
if not transmogInfo:IsEqual(currentInfo) then
model:TryOn(transmogInfo.appearanceID, (slotID == 16 and "MAINHANDSLOT") or "SECONDARYHANDSLOT", transmogInfo.illusionID); --ME FIXED?
--NarciPhotoModeOutfitSelect:ModifyPlayerTransmogInfo(model:GetID(), slotID, transmogInfo);
end
if slotID == 16 then
mainHandInfo = transmogInfo;
else
offHandInfo = transmogInfo;
end
--print(slotID.. " " ..transmogInfo.appearanceID)
else
model.equippedWeapons[hand] = nil;
end
NarciPhotoModeOutfitSelect:ModifyPlayerTransmogInfo(model:GetID(), mainHandInfo, offHandInfo);
end
elseif model.TryOn then
if transmogInfoList[16] then
model:TryOn(transmogInfoList[16], "MAINHANDSLOT", mainHandEnchant);
model.equippedWeapons[1] = transmogInfoList[16];
end
if transmogInfoList[17] then
model:TryOn(transmogInfoList[17], "SECONDARYHANDSLOT", offHandEnchant);
model.equippedWeapons[2] = transmogInfoList[17];
end
end
self.queue[inspecteeGUID] = nil;
After(0, function()
self.pauseUpdate = nil;
self:SetListener(false);
end)
--[[
for guid, m in pairs(self.queue) do
if m then
print("in queue: "..guid)
break
end
end
After(0, function()
self:SetListener(false);
end);
--]]
end
end
----------------------------------------------------------------------
local PMAI = CreateFrame("Frame", "Narci_PlayerModelAnimIn");
PMAI:Hide();
PMAI.t = 0
PMAI.faceTime = 0;
PMAI.trigger = true;
PMAI.init = true;
PMAI.useAlternateEntrance = true; --Enable entrance visual
function Narci:SetUseEntranceVisual()
local state = NarcissusDB.UseEntranceVisual;
if type(state) ~= "boolean" then
state = true;
end
PMAI.useAlternateEntrance = state;
end
local function PlayerModelAnimIn_Update_Style1(self, elapsed)
local ModelFrame = PrimaryPlayerModel;
self.t = self.t + elapsed;
local turnTime = 0.36;
local t = 1;
local offset = outQuad(self.t, startY, defaultY - startY, t);
if self.t > turnTime then
self.faceTime= self.faceTime + elapsed;
local radian = outSine(self.faceTime, -pi/2, endFacing + pi/2, 0.8); --0.11 NE
ModelFrame:SetFacing(radian);
ModelFrame.rotation = radian;
end
ModelFrame:SetPosition(0, offset, ModelFrame.posZ);
ModelFrame.posY = offset;
if self.t >= t then
ModelFrame.posX = 0;
self.t = 0;
self:Hide();
end
if self.t <=0.8 then
return;
elseif self.trigger then
self.trigger = false;
ModelFrame:PlayAnimation(804);
ModelFrame:MakeCurrentCameraCustom();
end
end
local function InitializeModel(model)
LightControl:CopyLightToNewModel(model);
local zoomLevel = -0.5;
model:MakeCurrentCameraCustom();
model:SetPortraitZoom(zoomLevel)
model:SetPosition(0, 0, defaultZ);
model:PlayAnimation(0, 0);
if model.isCameraDirty then
model.isCameraDirty = false;
After(0, function()
model:ResetCameraPosition();
end)
end
end
local EntranceAnimation;
do
local _, _, classID = UnitClass("player");
EntranceAnimation = Narci.ClassEntranceVisuals[classID];
end
PMAI:SetScript("OnShow", function(self) --PlayerModelAnimIn
local model = PrimaryPlayerModel;
--model:RefreshUnit();
SetModelByUnit(model, "player");
model.isItemLoaded = false;
model.isPlayer = true;
model.hasRaceChanged = false;
local ZoomMode = 2;
--if NarcissusDB.ShowFullBody then
-- ZoomMode = 2; --Full body
--else
-- ZoomMode = 1;
--end
AssignModelPositionTable();
local zoomLevel = TranslateValue[ZoomMode][1] or 0.05;
defaultY = TranslateValue[ZoomMode][2] or 0.4;
defaultZ = TranslateValue[ZoomMode][3] or -0.275;
model:SetPortraitZoom(zoomLevel);
model.zoomLevel = zoomLevel;
if (not self.useAlternateEntrance) or not EntranceAnimation then
model:SetPosition(0, startY, defaultZ);
model.posZ = defaultZ;
model:SetFacing(-pi/2);
model:FreezeAnimation(4, 1, 0);
model:SetAnimation(4);
self:SetScript("OnUpdate", PlayerModelAnimIn_Update_Style1);
else
local soundID = EntranceAnimation[6];
if soundID then
PlaySound(soundID, "SFX");
end
local animStart = EntranceAnimation[4]; --38
local startY = EntranceAnimation[1] or defaultY;
local startZ = EntranceAnimation[2] or defaultZ;
local startFacing = EntranceAnimation[3] or endFacing;
self.defaultY = defaultY;
self.defaultZ = defaultZ;
self.startY = startY;
self.startZ = startZ;
model:SetPosition(0, startY, startZ);
model.posY = startY;
model.posZ = startZ;
model:SetFacing(startFacing);
model.rotation = startFacing;
model:FreezeAnimation(animStart, 1, 0);
model:SetAnimation(animStart);
self:SetScript("OnUpdate", EntranceAnimation[5]);
end
model:Show();
model:SetModelAlpha(0);
model:SetAlpha(0);
model.isVirtual = false;
model:ResetCameraPosition();
FadeFrame(model, 0.6, 1);
--FadeFrame(ModelContainer, 0, 1);
if self.init then --Initialize settings
self.init = nil;
BasicPanel.ColorPresets.Color1:Click();
model:SetSheathed(true);
model:SetKeepModelOnHide(true);
end
model:SetActive(true);
WeaponUpdator:GetTargetWeapons("player");
end);
PMAI:SetScript("OnUpdate", PlayerModelAnimIn_Update_Style1);
PMAI:SetScript("OnHide", function(self)
self.t = 0;
self.faceTime = 0;
self.trigger = true;
end);
local PMAO = CreateFrame("Frame","Narci_PlayerModelAnimOut");
PMAO:Hide();
PMAO.t = 0
PMAO.faceTime = 0;
PMAO.trigger = true;
PMAO.Facing = 0;
PMAO.PosY = 0;
PMAO.PosZ = 0;
local function PlayerModelAnimOut_Update(self, elapsed)
local ModelFrame = PrimaryPlayerModel;
self.t = self.t + elapsed;
local turnTime = 0.3;
local t = 1;
local radian = outSine(self.t, self.Facing, pi/2 - self.Facing, turnTime); --0.11 NE
if self.t < turnTime then
ModelFrame:SetFacing(radian);
ModelFrame.rotation = radian;
end
if self.t > 0.2 then
self.faceTime= self.faceTime + elapsed;
local offset = PMAO.PosY + 1.15*self.faceTime/t;
ModelFrame:SetPosition(0, offset, self.PosZ);
ModelFrame.posY, ModelFrame.posZ = offset, PMAO.PosZ;
end
if self.t >= t then
SetModelByUnit(ModelFrame, "player");
self.t = 0;
self:Hide();
end
if self.t <=0.1 then
return;
elseif self.trigger then
self.trigger = false;
ModelFrame:SetAnimation(4);
end
end
local function HideAllModels()
for i, model in ipairs(ModelPool) do
model:ClearModel();
model.animationID = nil;
model.isCameraDirty = true;
end
end
PMAO:SetScript("OnShow", function(self)
GLOBAL_CAMERA_PITCH = pi/2;
self.Facing = PrimaryPlayerModel:GetFacing();
local _;
_, self.PosY, self.PosZ = PrimaryPlayerModel:GetPosition();
FadeFrame(SettingFrame, 0.4, 0)
ModelContainer:ClearOtherActors();
end)
PMAO:SetScript("OnUpdate", PlayerModelAnimOut_Update);
PMAO:SetScript("OnHide", function(self)
self.t = 0;
self.faceTime = 0;
self.trigger = true;
InitializePlayerInfo(1); --Reset Actor#1 portrait and name
SetModelByUnit(PrimaryPlayerModel, "player");
end);
----------------------------------------------------------------
local function UseCompactMode(state)
local frame = PrimaryPlayerModel;
if state then
FadeFrame(frame.GuideFrame, 0.5, 1, 0);
Narci_PlayerModelGuideFrame.VignetteRightSmall:Show();
FadeFrame(NarciModel_RightGradient, 0.5, 0);
else
FadeFrame(frame.GuideFrame, 0.5, 0);
FadeFrame(NarciModel_RightGradient, 0.5, 1)
end
end
local function CompactModeButton_OnHide(self)
HighlightButton(self, false);
self.isOn = false;
end
local Smooth_Zoom = CreateFrame("Frame");
Smooth_Zoom.t = 0;
Smooth_Zoom.duration = 0.2;
Smooth_Zoom:Hide();
local function UpdateCameraPosition(model)
--Spherical Coordinates since 1.0.7
SetModelCameraPosition(model, model.cameraDistance*sin(model.cameraPitch), 0, model.cameraDistance*cos(model.cameraPitch) + 0.8);
end
local function UpdateCameraPitch(model, pitch)
model.cameraPitch = pitch;
UpdateCameraPosition(model);
end
local function UpdateGlobalCameraPitch(pitch)
local model;
for i = 1, #ModelFrames do
model = ModelFrames[i];
if model and not model.isVirtual then
model.cameraPitch = pitch;
UpdateCameraPosition(model);
end
end
GLOBAL_CAMERA_PITCH = pitch;
end
local function ResetAllCameraPitch()
GLOBAL_CAMERA_PITCH = pi/2;
for _, model in pairs(ModelFrames) do
model.cameraPitch = GLOBAL_CAMERA_PITCH;
UpdateCameraPitch(model, model.cameraPitch);
end
end
local function Smooth_Zoom_Update(self, elapsed)
self.t = self.t + elapsed
local EndPoint = self.EndPoint;
local StartPoint = self.StartPoint;
local Value = outSine(self.t, StartPoint, EndPoint - StartPoint, self.duration) --0.11 NE
if LINK_SCALE then
for i = 1, #ModelFrames do
--ModelFrames[i]:SetCameraDistance(Value);
ModelFrames[i].cameraDistance = Value;
UpdateCameraPosition(ModelFrames[i]);
end
else
--ModelFrames[ACTIVE_MODEL_INDEX]:SetCameraDistance(Value);
--print(Value)
ModelFrames[ACTIVE_MODEL_INDEX].cameraDistance = Value;
UpdateCameraPosition(ModelFrames[ACTIVE_MODEL_INDEX]);
end
if self.t >= self.duration then
self:Hide();
end
end
Smooth_Zoom:SetScript("OnShow", function(self)
self.StartPoint = ModelFrames[ACTIVE_MODEL_INDEX].cameraDistance;
end);
Smooth_Zoom:SetScript("OnUpdate", Smooth_Zoom_Update);
Smooth_Zoom:SetScript("OnHide", function(self)
self.t = 0
end);
local function SmoothZoomModel(EndPoint)
Smooth_Zoom:Hide();
Smooth_Zoom.EndPoint = EndPoint;
Smooth_Zoom:Show();
end
local function Narci_ShowChromaKey(state)
local frame = FullSceenChromaKey;
if state then
FadeFrame(frame, 0.25, 1);
Narci_Character:SetShown(false);
else
FadeFrame(frame, 0.5, 0);
if Narci_SlotLayerButton.isOn then
Narci_Character:SetShown(true);
end
end
end
--- Show Alpha Channel ---
local function ShowTextAlphaChannel(state, doNotShowModel)
--Text Mask
local slotTable = Narci_Character.slotTable;
if not (slotTable) then
return;
end
local theme = NarcissusDB.BorderTheme;
local borderMask;
local shadowAlpha = false;
local runeAlpha = 1;
if theme == "Bright" then
borderMask = "Interface/AddOns/Narcissus/Art/Masks/HexagonThin-Mask";
elseif theme == "Dark" then
borderMask = "Interface/AddOns/Narcissus/Art/Masks/HexagonThick-Mask";
shadowAlpha = true;
runeAlpha = 0;
end
local slot, sourcePlainText, tempText;
if state then
for i=1, #slotTable do
slot = slotTable[i];
if slot then
--slotTable[i].Name:SetFont(font, Height);
if slot.RuneSlot then
--slot.RuneSlot.AlphaChannelRune:Show();
--slot.RuneSlot.Background:SetAlpha(runeAlpha);
end
slot.GradientBackground:SetColorTexture(1, 1, 1);
slot.Name:SetTextColor(1, 1, 1);
slot.Name:SetShadowColor(1, 1, 1);
tempText = slot.Name:GetText();
slot.Name:SetText(" "); --IDK why shadow color won't be updated until the text got
slot.Name:SetText(tempText);
sourcePlainText = slot.sourcePlainText;
if sourcePlainText then
slot.ItemLevel:SetText(" ");
slot.ItemLevel:SetText(sourcePlainText);
end
slot.ItemLevel:SetTextColor(1, 1, 1);
slot.ItemLevel:SetShadowColor(1, 1, 1);
slot:ShowAlphaChannel();
end
end
ModelContainer:Hide();
Narci_XmogNameFrame:Hide();
Narci_Character:SetAlpha(1);
Narci_Character:Show();
else
for i=1, #slotTable do
slot = slotTable[i];
if slot then
--slotTable[i].Name:SetFont(font, Height);
if slot.RuneSlot then
--slot.RuneSlot.AlphaChannelRune:Hide();
--slot.RuneSlot.Background:SetAlpha(runeAlpha);
end
slot.GradientBackground:SetColorTexture(0, 0, 0);
slot.Name:SetShadowColor(0, 0, 0);
slot.ItemLevel:SetShadowColor(0, 0, 0);
slot:Refresh();
end
end
if not doNotShowModel then
ModelContainer:Show();
ModelContainer:SetAlpha(1);
Narci_XmogNameFrame:Show();
Narci_XmogNameFrame:SetAlpha(1);
end
end
end
local hasBackup = false;
local LayerButtonStates = {};
local function UnhighlightAllLayerButtons()
local buttons = BasicPanel.LayerButtons;
if not hasBackup then
wipe(LayerButtonStates);
end
for i=1, #buttons do
if not hasBackup then
tinsert(LayerButtonStates, buttons[i].isOn);
end
buttons[i].isOn = false;
buttons[i]:UnlockHighlight();
buttons[i].Label:SetTextColor(0.65, 0.65, 0.65) --
buttons[i].AlphaButton.isOn = false;
buttons[i].AlphaButton:UnlockHighlight();
end
hasBackup = true;
end
local function RestoreAllLayerButtons()
local buttons = BasicPanel.LayerButtons;
for i=1, #buttons do
local state = LayerButtonStates[i];
buttons[i].isOn = state
buttons[i].AlphaButton.isOn = false;
buttons[i].AlphaButton:UnlockHighlight();
--print(i..": "..tostring(state))
HighlightButton(buttons[i], state);
end
hasBackup = false;
end
local function ExitAlphaMode()
local buttons = BasicPanel.AlphaButtons;
for i= 1, #buttons do
if buttons[i].isOn then
buttons[i]:Click()
return true;
end
end
return false;
end
local function LayerButton_OnClick(self)
if ExitAlphaMode() then
return;
end
self.isOn = not self.isOn;
HighlightButton(self, self.isOn, true);
end
local function SlotLayerButton_OnClick(self)
LayerButton_OnClick(self);
--Narci_Character:SetShown(self.isOn);
if self.isOn then
if PrimaryPlayerModel.xmogMode == 2 then
FadeFrame(NarciModel_RightGradient, 0.25, 1);
end
FadeFrame(Narci_Character, 0.25, 1);
else
FadeFrame(NarciModel_RightGradient, 0.25, 0);
FadeFrame(Narci_Character, 0.25, 0);
end
end
local function PlayerModelLayerButton_OnClick(self)
LayerButton_OnClick(self);
local model = ModelContainer;
model:SetShown(self.isOn);
end
local function ChangeHighlight(self)
self.isOn = not self.isOn;
if self.isOn then
UnhighlightAllLayerButtons();
self.isOn = true;
self:LockHighlight();
self:GetParent().Label:SetTextColor(0.88, 0.88, 0.88)
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
else
RestoreAllLayerButtons();
self:UnlockHighlight();
self.isOn = false;
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF);
end
end
local function SetTextAlphaLayerButtonVisual(self)
if Narci_PlayerModelLayerButton.AlphaButton.isOn then
Narci_PlayerModelLayerButton.AlphaButton:Click();
end
ChangeHighlight(self);
if self.isOn then
FadeFrame(FullScreenAlphaChannel, 0.5, 1);
else
FadeFrame(FullScreenAlphaChannel, 0.5, 0);
local SlotLayerButton = self:GetParent();
SlotLayerButton.isOn = true;
SlotLayerButton:LockHighlight();
SlotLayerButton.Label:SetTextColor(0.88, 0.88, 0.88);
end
end
local function TextAlphaLayerButton_OnClick(self)
SetTextAlphaLayerButtonVisual(self);
ShowTextAlphaChannel(self.isOn);
end
local function TextAlphaLayerButton_OnHide(self)
if self.isOn then
SetTextAlphaLayerButtonVisual(self);
ShowTextAlphaChannel(false, true);
end
end
local function ModelAlphaLayerButton_OnClick(self)
if Narci_SlotLayerButton.AlphaButton.isOn then
Narci_SlotLayerButton.AlphaButton:Click();
end
ChangeHighlight(self);
Narci_ShowChromaKey(self.isOn);
local parent = self:GetParent();
if self.isOn then
parent.ButtonFrame:Show();
if not parent.lastSelectedButton then
parent.ButtonFrame.buttons[4]:Click(); --Model Mask
else
parent.lastSelectedButton:Click();
end
else
parent.ButtonFrame:Hide();
end
end
local function ModelAlphaLayerButton_OnHide(self)
if self.isOn then
self.isOn = false;
self:UnlockHighlight();
self:GetParent().Label:SetTextColor(0.65, 0.65, 0.65);
end
end
local function SlotLayerButton_OnShow(self)
local isShown = Narci_Character:IsShown()
self.isOn = isShown;
HighlightButton(self, isShown);
end
local function LightsOut(state)
local model;
if state then
for i = 1, #ModelFrames do
model = ModelFrames[i];
if model then
model:SetFogColor(1, 1, 1);
end
end
else
for i = 1, #ModelFrames do
model = ModelFrames[i];
if model then
model:ClearFog()
end
end
end
end
function Narci_LayerButton_OnLoad(self)
self.isOn = true;
self:LockHighlight();
local ID = self:GetID();
local AlphaButton = self.AlphaButton;
AlphaButton.isOn = false;
if ID == 1 then
--Equipment Slots Visibility
self.Label:SetText(L["Equipment Slots"]);
self.Icon:SetTexCoord(0.5, 0.703125, 0.703125, 0.890625);
self:SetScript("OnClick", SlotLayerButton_OnClick);
self:SetScript("OnShow", SlotLayerButton_OnShow);
self.tooltipDescription = L["Toggle Equipment Slots"];
--Use white font to replace item texts
AlphaButton:SetScript("OnClick", TextAlphaLayerButton_OnClick);
AlphaButton:SetScript("OnHide", TextAlphaLayerButton_OnHide);
AlphaButton.tooltipDescription = L["Toggle Text Mask"];
elseif ID == 2 then
--3D Model Visibility
self.Label:SetText(L["3D Model"]);
self:SetScript("OnClick", PlayerModelLayerButton_OnClick);
self:SetScript("OnShow", function(f)
HighlightButton(f, true);
f.isOn = ModelContainer:IsShown();
end)
self.tooltipDescription = L["Toggle 3D Model"];
--Show chroma key (mask, green/blue screen)
AlphaButton:SetScript("OnClick", ModelAlphaLayerButton_OnClick);
AlphaButton:SetScript("OnHide", ModelAlphaLayerButton_OnHide);
AlphaButton.tooltipDescription = L["Toggle Model Mask"];
--Create Chromakey Buttons
local ButtonFrame = self.ButtonFrame;
local buttons = {};
local function SelectButton(button)
button.Border:SetTexCoord(0.5, 1, 0, 1);
for i = 1, 4 do
if button ~= buttons[i] then
buttons[i].Border:SetTexCoord(0, 0.5, 0, 1);
end
end
self.lastSelectedButton = button;
end
local function ChromakeyButton_OnClick(button)
SelectButton(button);
ModelContainer.ChromaKey:SetColorTexture(button.r, button.g, button.b);
LightsOut(false);
end
local function LightsOutButton_OnClick(button)
SelectButton(button);
ModelContainer.ChromaKey:SetColorTexture(0, 0, 0);
button.isOn = true;
LightsOut(true);
end
for i = 1, 4 do
local button = CreateFrame("Button", nil, ButtonFrame, "Narci_RoundButtonTemplate");
tinsert(buttons, button);
local r, g, b;
if i == 1 then
button:SetPoint("RIGHT", self, "RIGHT", -10, 0);
r, g, b = 0, 177/255, 64/255; --Green
else
button:SetPoint("RIGHT", buttons[i - 1], "LEFT", 0, 0);
if i == 2 then
r, g, b = 0, 71/255, 187/255; --Blue
elseif i == 3 then
r, g, b = 0, 0 ,0;
elseif i == 4 then
r, g, b = 1, 1 ,1;
end
end
button.r, button.g, button.b = r, g, b;
if i == 3 then
r, g, b = 0.12, 0.12, 0.12;
end
button.Color:SetColorTexture(r, g, b);
if i == 4 then
button:SetScript("OnClick", LightsOutButton_OnClick);
button:SetScript("OnHide", function(button)
if button.isOn then
LightsOut(false);
end
end);
else
button:SetScript("OnClick", ChromakeyButton_OnClick);
end
end
ButtonFrame.buttons = buttons;
end
local Settings = self:GetParent();
if not Settings.LayerButtons then
Settings.LayerButtons = {};
end
tinsert(Settings.LayerButtons, self);
if not Settings.AlphaButtons then
Settings.AlphaButtons = {};
end
tinsert(Settings.AlphaButtons, AlphaButton);
end
function Narci_BackgroundColorButton_OnClick(self)
ModelContainer.ChromaKey:SetColorTexture(self.r, self.g, self.b);
self.Border:Show();
self.Border:SetTexCoord(0.5, 1, 0, 1);
local parent = self:GetParent();
parent.Blue.Border:SetTexCoord(0, 0.5, 0, 1);
parent.Black.Border:SetTexCoord(0, 0.5, 0, 1);
local WhiteButton = parent.White;
if WhiteButton.isOn then
WhiteButton:Click();
end
parent.lastSelectedButton = self;
end
local AutoCloseTimer = C_Timer.NewTimer(0, function() end)
function Narci_AnimationOption_MainTabButton_OnClick(self)
AutoCloseTimer:Cancel()
self.isOn = not self.isOn;
if self.isOn then
--self.Background:SetTexCoord(0, 0.376953125, 0.6328125, 0.52734375);
self.Arrow:SetTexCoord(0, 1, 0, 1);
self:GetParent().OtherTab:Show();
else
--self.Background:SetTexCoord(0, 0.376953125, 0.2109375, 0.31640625);
self.Arrow:SetTexCoord(0, 1, 1, 0);
self:GetParent().OtherTab:Hide();
end
AutoCloseTimer = C_Timer.NewTimer(5, function()
if Narci_AnimationOptionFrame_Tab1.isOn then
Narci_AnimationOptionFrame_Tab1:Click();
end
end)
end
local animationIDPresets = {
--from right to left
[1] = {110, 48, 109, 29, ["name"] = L["Ranged Weapon"],},
[2] = {962, 1242, 1240, 1076, ["name"] = L["Melee Animation"],},
[3] = {124, 51, 874, 940, ["name"] = L["Spellcasting"],},
}
function Narci_AnimationOptionFrame_OnLoad(self)
local _, _, classID = UnitClass("player");
local ID;
if classID == 5 or classID == 8 or classID == 9 or classID == 11 then --spellcasting
ID = 3;
elseif classID == 3 then --hunter
ID = 1;
else
ID = 2;
end
self.tab1:SetID(ID);
self.tab1.Label:SetText(animationIDPresets[ID]["name"]);
local maxTab = 3;
local otherIDs = {};
for i=1, maxTab do
if i ~= ID then
tinsert(otherIDs, i)
end
end
self.OtherTab.tab2:SetID(otherIDs[1]);
self.OtherTab.tab2.Label:SetText(animationIDPresets[otherIDs[1]]["name"]);
self.OtherTab.tab3:SetID(otherIDs[2]);
self.OtherTab.tab3.Label:SetText(animationIDPresets[otherIDs[2]]["name"]);
local buttons = self.buttons;
for i=1, #buttons do
buttons[i].ID = (animationIDPresets[ID][i]);
end
NarciPhotoModeBar_OnLoad(self);
end
function Narci_AnimationOption_OtherTabButton_OnClick(self)
local ID = self:GetID();
local tab1 = self:GetParent():GetParent().tab1;
local activeID = tab1:GetID();
local buttons = self:GetParent():GetParent().buttons;
local animationID;
for i=1, #buttons do
buttons[i].ID = (animationIDPresets[ID][i]);
buttons[i].animOut:Play();
end
self:SetID(activeID);
self.Label:SetText(animationIDPresets[activeID]["name"]);
tab1:SetID(ID);
tab1.Label:SetText(animationIDPresets[ID]["name"]);
tab1:Click();
end
function Narci_AnimationPresetButton_OnClick(self, button)
local id = self.ID;
local model = ModelFrames[ACTIVE_MODEL_INDEX];
model:PlayAnimation(id);
if button == "RightButton" then
AnimationIDEditBox:SetAnimationID(id);
end
local buttons = self:GetParent().buttons;
for i=1, #buttons do
buttons[i].Highlight:Hide();
buttons[i].isOn = false;
end
self.isOn = true;
self.Highlight:Show();
end
function Narci_Model_DarknessSlider_OnValueChanged(self, value, isUserInput)
self.VirtualThumb:SetPoint("CENTER", self.Thumb, "CENTER", 0, 0)
if value ~= self.oldValue then
self.oldValue = value
Narci_BackgroundDarkness:Show();
Narci_BackgroundDarkness:SetAlpha(value);
end
end
function Narci_Model_VignetteSlider_OnValueChanged(self, value, isUserInput)
self.VirtualThumb:SetPoint("CENTER", self.Thumb, "CENTER", 0, 0)
if value ~= self.oldValue then
self.oldValue = value
Narci_VignetteLeft:SetAlpha(value);
Narci_VignetteRightLarge:SetAlpha(value);
Narci_VignetteRightSmall:SetAlpha(value);
Narci_PlayerModelGuideFrame.VignetteRightSmall:SetAlpha(value);
end
end
function Narci_Model_UseCompactMode_OnClick(self)
self.isOn = not self.isOn;
if self.isOn then
HighlightButton(self, true, true);
if not Narci_HidePlayerButton.isOn then
Narci_HidePlayerButton:Click();
end
else
HighlightButton(self, false, true);
if Narci_HidePlayerButton.isOn then
Narci_HidePlayerButton:Click();
end
end
UseCompactMode(self.isOn);
end
function Narci_Model_HidePlayer_OnClick(self)
self.isOn = not self.isOn;
ConsoleExec("showPlayer");
HighlightButton(self, self.isOn, true);
end
function Narci_ModelShadow_SizeSlider_OnValueChanged(self, value, isUserInput)
self.VirtualThumb:SetPoint("CENTER", self.Thumb, "CENTER", 0, 0)
if value ~= self.oldValue then
self.oldValue = value;
if not self.shadows then
self.shadows = self:GetParent():GetParent().ShadowTextures;
end
self.shadows:SetScale(value);
end
end
function Narci_ModelShadow_AlphaSlider_OnValueChanged(self, value, isUserInput)
self.VirtualThumb:SetPoint("CENTER", self.Thumb, "CENTER", 0, 0)
if value ~= self.oldValue then
self.oldValue = value;
if not self.shadow1 then
self.shadow1 = self:GetParent():GetParent().ShadowTextures.Shadow;
end
if not self.shadow2 then
self.shadow2 = self:GetParent():GetParent().ShadowTextures.RadialShadow;
end
self.shadow1:SetAlpha(value);
self.shadow2:SetAlpha(value);
end
end
-------------------------
---- Custom Lighting ----
-------------------------
local LightData = {};
function LightData:SetAmbientMode(state)
self.ambientMode = state;
end
function LightData:SetLightDirection(dirX, dirY, dirZ)
self.dirX, self.dirY, self.dirZ = dirX, dirY, dirZ;
end
function LightData:GetLightDirection()
return self.dirX, self.dirY, self.dirZ;
end
function LightData:SetAmbientColor(r, g, b)
self.ambR, self.ambG, self.ambB = r, g, b;
end
function LightData:GetAmbientColor()
return self.ambR, self.ambG, self.ambB;
end
function LightData:SetDiffuseColor(r, g, b)
self.dirR, self.dirG, self.dirB = r, g, b;
end
function LightData:GetDiffuseColor()
return self.dirR, self.dirG, self.dirB;
end
function LightData:Set(dirX, dirY, dirZ, dirR, dirG, dirB, ambR, ambG, ambB)
self:SetLightDirection(dirX, dirY, dirZ);
self:SetDiffuseColor(dirR, dirG, dirB);
self:SetAmbientColor(ambR, ambG, ambB);
end
local XdirX, XdirY, XdirZ, XdirR, XdirG, XdirB;
local function SetLightViewerColor(r, g, b)
if LightControl.ambientMode then
BasicPanel.TopView.AmbientColor:SetColorTexture(r, g, b, 0.6);
BasicPanel.SideView.AmbientColor:SetColorTexture(r, g, b, 0.6);
else
BasicPanel.TopView.LightColor:SetVertexColor(r, g, b, 0.6);
BasicPanel.SideView.LightColor:SetVertexColor(r, g, b, 0.6);
end
end
local function ShowHighlightBorder(border)
border:SetTexCoord(0.5, 1, 0, 1);
end
local function HideHighlightBorder(border)
border:SetTexCoord(0, 0.5, 0, 1);
end
function Narci_LightColorButton_OnClick(self)
--Change Light Color--
local H, S, V = RGB2HSV(self.r, self.g, self.b);
local ColorSliders = BasicPanel.ColorSliders;
if H then ColorSliders.HueSlider:SetValue(H, true); end
if S then ColorSliders.SaturationSlider:SetValue(S, true); end
if V then ColorSliders.BrightnessSlider:SetValue(V, true); end
SetLightViewerColor(self.r/255, self.g/255, self.b/255);
local ColorButtons = self:GetParent().Colors;
for i=1, #ColorButtons do
HideHighlightBorder(ColorButtons[i].Border);
end
ShowHighlightBorder(self.Border);
end
function Narci_LightColorButton_OnLoad(self)
local r, g, b = 0, 0, 0;
local id = self:GetID();
if id == 1 then
r, g, b = 204, 204, 204;
elseif id == 2 then
r, g, b = 0.65*255, 0.45*255, 0.7*255; --
elseif id == 3 then
r, g, b = 140, 70, 70
elseif id == 4 then
r, g, b = 220, 173, 83; --
elseif id == 5 then
r, g, b = 80, 186, 141;
elseif id == 6 then
r, g, b = 0, 174, 239;
elseif id == 7 then
r, g, b = 40, 124, 186; --
elseif id == 8 then
r, g, b = 70, 61, 220;
end
self.r = r;
self.g = g;
self.b = b;
self.Color:SetColorTexture(r / 255, g / 255, b / 255, 1);
if not self:GetParent().Colors then
self:GetParent().Colors = {};
end
tinsert(self:GetParent().Colors, self)
end
---------------------------
---------------------------
---------------------------
local NUM_UNCAPTURED_LAYERS = -1;
local Temps = {
Alpha2 = 1,
Vignette = 0,
Brightness = 0,
HidePlayer = false,
};
local function PauseAllModel(bool)
for i = 1, #ModelFrames do
ModelFrames[i]:SetPaused(bool);
end
end
local function StartAutoCapture()
local model = ModelContainer;
local r1, g1, b1 = 0, 177/255, 64/255;
local r2, g2, b2 = 0, 71/255, 187/255;
if NUM_UNCAPTURED_LAYERS == 6 then
PauseAllModel(true);
Temps.TextOverlayVisibility = NarciTextOverlayContainer:IsShown();
NarciTextOverlayContainer:Hide();
Temps.HidePlayer = Narci_HidePlayerButton.isOn;
if not Temps.HidePlayer then
Narci_HidePlayerButton:Click();
end
Temps.Vignette = Narci_Model_VignetteSlider:GetValue();
Temps.Brightness = Narci_Model_DarknessSlider:GetValue();
Narci_Model_VignetteSlider:SetValue(0);
Narci_Model_DarknessSlider:SetValue(0);
Narci_Character:Hide();
model:Hide();
elseif NUM_UNCAPTURED_LAYERS == 5 then
model:Show();
FullSceenChromaKey:SetColorTexture(0, 0, 0);
FullSceenChromaKey:Show();
FullSceenChromaKey:SetAlpha(1);
LightsOut(true);
elseif NUM_UNCAPTURED_LAYERS == 4 then
LightsOut(false);
model:Show();
FullSceenChromaKey:SetColorTexture(r1, g1, b1);
FullSceenChromaKey:Show();
FullSceenChromaKey:SetAlpha(1);
elseif NUM_UNCAPTURED_LAYERS == 3 then
model:Show();
FullSceenChromaKey:SetColorTexture(r2, g2, b2);
FullSceenChromaKey:Show();
FullSceenChromaKey:SetAlpha(1);
elseif NUM_UNCAPTURED_LAYERS == 2 then
model:Hide();
FullSceenChromaKey:Hide();
FullSceenChromaKey:SetAlpha(0);
ShowTextAlphaChannel(true);
FullScreenAlphaChannel:SetAlpha(1);
FullScreenAlphaChannel:Show();
elseif NUM_UNCAPTURED_LAYERS == 1 then
ShowTextAlphaChannel(false);
FullScreenAlphaChannel:SetAlpha(1);
FullScreenAlphaChannel:Show();
model:Hide();
elseif NUM_UNCAPTURED_LAYERS == 0 then
Narci_Model_VignetteSlider:SetValue(Temps.Vignette);
Narci_Model_DarknessSlider:SetValue(Temps.Brightness);
if Temps.TextOverlayVisibility then
NarciTextOverlayContainer:Show();
end
model:Show();
FullScreenAlphaChannel:SetAlpha(0);
FullScreenAlphaChannel:Hide();
if not Temps.HidePlayer then
Narci_HidePlayerButton:Click();
end
NUM_UNCAPTURED_LAYERS = -1;
CaptureButton.Value:SetText(0);
CaptureButton:Enable();
local button = Narci_SlotLayerButton;
button:LockHighlight();
button.Label:SetTextColor(0.8, 0.8, 0.8);
button.isOn = true;
PauseAllModel(false);
FullSceenChromaKey:Hide();
FullSceenChromaKey:SetAlpha(0);
return;
else
NUM_UNCAPTURED_LAYERS = -1;
CaptureButton.Value:SetText(0);
CaptureButton:Enable();
PauseAllModel(false);
return;
end
After(1, function()
Screenshot();
end)
CaptureButton.Value:SetText(NUM_UNCAPTURED_LAYERS);
NUM_UNCAPTURED_LAYERS = NUM_UNCAPTURED_LAYERS - 1;
end
local function StartAutoCapture_SkipItems()
local model = ModelContainer;
local r1, g1, b1 = 0, 177/255, 64/255;
local r2, g2, b2 = 0, 71/255, 187/255;
if NUM_UNCAPTURED_LAYERS == 4 then
PauseAllModel(true);
Temps.TextOverlayVisibility = NarciTextOverlayContainer:IsShown();
NarciTextOverlayContainer:Hide();
Temps.HidePlayer = Narci_HidePlayerButton.isOn;
if not Temps.HidePlayer then
Narci_HidePlayerButton:Click();
end
Temps.Vignette = Narci_Model_VignetteSlider:GetValue();
Temps.Brightness = Narci_Model_DarknessSlider:GetValue();
Narci_Model_VignetteSlider:SetValue(0);
Narci_Model_DarknessSlider:SetValue(0);
Narci_Character:Hide();
model:Hide();
elseif NUM_UNCAPTURED_LAYERS == 3 then
model:Show();
FullSceenChromaKey:SetColorTexture(0, 0, 0);
FullSceenChromaKey:Show();
FullSceenChromaKey:SetAlpha(1);
LightsOut(true);
elseif NUM_UNCAPTURED_LAYERS == 2 then
LightsOut(false);
model:Show();
FullSceenChromaKey:SetColorTexture(r1, g1, b1);
FullSceenChromaKey:Show();
FullSceenChromaKey:SetAlpha(1);
elseif NUM_UNCAPTURED_LAYERS == 1 then
model:Show();
FullSceenChromaKey:SetColorTexture(r2, g2, b2);
FullSceenChromaKey:Show();
FullSceenChromaKey:SetAlpha(1);
elseif NUM_UNCAPTURED_LAYERS == 0 then
Narci_Model_VignetteSlider:SetValue(Temps.Vignette);
Narci_Model_DarknessSlider:SetValue(Temps.Brightness);
if Temps.TextOverlayVisibility then
NarciTextOverlayContainer:Show();
end
model:Show();
FullScreenAlphaChannel:SetAlpha(0);
FullScreenAlphaChannel:Hide();
if not Temps.HidePlayer then
Narci_HidePlayerButton:Click();
end
NUM_UNCAPTURED_LAYERS = -1;
CaptureButton.Value:SetText(0);
CaptureButton:Enable();
local button = Narci_SlotLayerButton;
button:LockHighlight();
button.Label:SetTextColor(0.8, 0.8, 0.8);
button.isOn = true;
PauseAllModel(false);
FullSceenChromaKey:Hide();
FullSceenChromaKey:SetAlpha(0);
return;
else
NUM_UNCAPTURED_LAYERS = -1;
CaptureButton.Value:SetText(0);
CaptureButton:Enable();
PauseAllModel(false);
return;
end
After(1, function()
Screenshot();
end)
CaptureButton.Value:SetText(NUM_UNCAPTURED_LAYERS);
NUM_UNCAPTURED_LAYERS = NUM_UNCAPTURED_LAYERS - 1;
end
--[[
-----------------
-------API-------
-----------------
SetShadowEffect(0~1) --Transparent
function SM(path)
path = tostring(path)
path = gsub(path, "%/", "\\".."\\")
print(path)
PrimaryPlayerModel:SetModel(path)
end
function EQ(id)
local _, itemLink = GetItemInfo(id)
PrimaryPlayerModel:TryOn(itemLink)
end
function SV(id)
PrimaryPlayerModel:ApplySpellVisualKit(id, false)
end
--]]
-----------------------------------------------------------------------------
NarciAnimationIDEditboxMixin = {};
function NarciAnimationIDEditboxMixin:OnLoad()
self.isOn = false;
self:SetAnimationID(0);
self.Highlight:SetAlpha(0);
self.FavoriteButton = self:GetParent().FavoriteButton;
self:SetHighlightColor(0, 0, 0);
AnimationIDEditBox = self;
self:SetScript("OnLoad", nil);
self.OnLoad = nil;
end
function NarciAnimationIDEditboxMixin:OnMouseWheel(delta)
local id = self:GetNumber();
if id > maxAnimationID then
id = maxAnimationID;
end
local model = ModelFrames[ACTIVE_MODEL_INDEX];
if delta < 0 and id < maxAnimationID then
id = id + 1;
while (not model:HasAnimation(id)) and id < maxAnimationID do
id = id + 1;
end
elseif delta > 0 and id > 0 then
id = id - 1;
while (not model:HasAnimation(id)) and id > 0 do
id = id - 1;
end
end
self.isOn = true;
model:PlayAnimation(id);
if not self.hasWheeled then
self.hasWheeled = true;
DisablePauseButton();
self.MouseButton:FadeOut();
end
self:SetAnimationID(id);
end
function NarciAnimationIDEditboxMixin:SetAnimationID(id)
self:SetNumber(id);
self.IDFrame.Label:SetText( NarciAnimationInfo.GetOfficialName(id) );
end
function NarciAnimationIDEditboxMixin:OnEnterPressed()
self.Highlight:SetAlpha(0);
if not self:GetText() then
self:ClearFocus();
return;
else
self:ClearFocus();
end
local model = ModelFrames[ACTIVE_MODEL_INDEX];
local id = math.min(self:GetNumber(), maxAnimationID);
model.animationID = id;
if model.isPaused then
NarciModelControl_AnimationSlider:SetValue(0, true);
else
model:PlayAnimation(id);
end
end
function NarciAnimationIDEditboxMixin:OnEditFocusLost()
self:HighlightText(0,0);
self.Highlight:SetAlpha(0);
local ID = tonumber(self:GetText());
if not ID then
self:SetText(self.oldID);
elseif ID > maxAnimationID then
self:SetText(maxAnimationID);
end
self.Timer:Stop();
end
function NarciAnimationIDEditboxMixin:OnEditFocusGained()
self.oldID = self:GetNumber();
self:HighlightText();
end
function NarciAnimationIDEditboxMixin:OnEnter()
self.Timer:Stop();
FadeFrame(self.Highlight, 0.2, 1);
self.IDFrame:Show();
self.MouseButton:ShowTooltip();
end
function NarciAnimationIDEditboxMixin:OnLeave()
if not self:HasFocus() then
FadeFrame(self.Highlight, 0.2, 0);
else
self.Timer:Play();
end
self.hasWheeled = nil;
self.IDFrame:Hide();
self.MouseButton:FadeOut();
end
function NarciAnimationIDEditboxMixin:OnTextChanged()
self.Timer:Stop();
local id = self:GetNumber();
self.IDFrame.Label:SetText( NarciAnimationInfo.GetOfficialName(id) );
self.FavoriteButton:UpdateStatus(id);
end
function NarciAnimationIDEditboxMixin:OnEscapePressed()
self:ClearFocus();
end
function NarciAnimationIDEditboxMixin:OnSpacePressed()
self:HighlightText();
end
function NarciAnimationIDEditboxMixin:OnHide()
self:ClearFocus();
end
NarciAnimationVariationSphereMixin = {};
function NarciAnimationVariationSphereMixin:SetVisual(variationID)
if variationID <= 3 then
local left = variationID * 0.25;
self.Icon:SetTexCoord(left, left + 0.25, 0, 1);
self.Icon:Show();
self.IDText:Hide();
else
self.Icon:Hide();
self.IDText:Show();
self.IDText:SetText(variationID);
end
self.variationID = variationID;
end
function NarciAnimationVariationSphereMixin:OnLoad()
VariationButton = self;
self.maxVariations = 3; -- 0, 1, 2, 3
self.Icon:SetSize(12, 12);
self.Icon:SetTexture("Interface/AddOns/Narcissus/Art/Widgets/ModelAnimation/VariationSphere", nil, nil, "TRILINEAR");
self:SetVisual(0);
self.tooltipDescription = L["Animation Variation"];
end
function NarciAnimationVariationSphereMixin:OnEnter()
self.Icon:SetSize(14, 14);
WidgetTooltip:ShowButtonTooltip(self, 0, nil, 1);
end
function NarciAnimationVariationSphereMixin:OnLeave()
self.Icon:SetSize(12, 12);
WidgetTooltip:HideTooltip();
end
function NarciAnimationVariationSphereMixin:OnClick(button)
local newVariationID;
if button == "LeftButton" then
if self.variationID < self.maxVariations then
newVariationID = self.variationID + 1;
else
newVariationID = 0;
end
elseif button == "RightButton" then
if self.variationID > 0 then
newVariationID = self.variationID - 1;
else
newVariationID = self.maxVariations;
end
elseif button == "MiddleButton" then
newVariationID = 4;
self.maxVariations = 20; --hidden feature: uncap variationID
end
self:SetVisual(newVariationID);
---Update Model Animation
local model = ModelFrames[ACTIVE_MODEL_INDEX];
local animationID = AnimationIDEditBox:GetNumber();
if model.isPaused then
model.variationID = newVariationID;
NarciModelControl_AnimationSlider:SetValue(model.freezedFrame or 0, true);
else
model:PlayAnimation(animationID, newVariationID);
end
end
function NarciAnimationVariationSphereMixin:OnMouseDown()
end
NarciFavoriteStarMixin = {};
function NarciFavoriteStarMixin:OnLoad()
self.Icon:SetSize(16, 16);
self.Star:SetSize(16, 16);
self.Star:SetTexCoord(0.25, 0.5, 0, 1);
local file = "Interface/AddOns/Narcissus/Art/Widgets/SpellVisualBrowser/Favorites.tga";
self.Icon:SetTexture(file, nil, nil, "LINEAR"); --TRILINEAR
self.Star:SetTexture(file, nil, nil, "LINEAR");
local isFavorite = false;
self:SetVisual(isFavorite);
local HollowStar = self:GetParent().ExpandButton.Star;
--HollowStar:ClearAllPoints();
--HollowStar:SetPoint("CENTER", self.Star, "CENTER", 0, 0);
self.flyOut1 = self.Star.flyOut;
self.flyOut2 = HollowStar.flyOut;
end
function NarciFavoriteStarMixin:OnEnter()
self:SetAlpha(1);
if self.isFavorite then
WidgetTooltip:NewText(self, L["Favorites Remove"], nil, nil, 1);
else
WidgetTooltip:NewText(self, L["Favorites Add"], nil, nil, 1);
end
end
function NarciFavoriteStarMixin:OnLeave()
if not self.isFavorite then
self:SetAlpha(0.6);
end
WidgetTooltip:HideTooltip();
end
function NarciFavoriteStarMixin:OnMouseDown()
self.Icon:SetSize(14, 14);
end
function NarciFavoriteStarMixin:OnMouseUp()
self.Icon:SetSize(16, 16);
end
function NarciFavoriteStarMixin:PlayStarAnimation()
self.flyOut1:Stop();
self.flyOut2:Stop();
self.flyOut1:Play();
self.flyOut2:Play();
end
function NarciFavoriteStarMixin:SetVisual(isFavorite)
self.isFavorite = isFavorite;
if isFavorite then
self.Icon:SetTexCoord(0.25, 0.5, 0, 1);
self:SetAlpha(1);
else
self.Icon:SetTexCoord(0, 0.25, 0, 1);
self:SetAlpha(0.6);
end
end
function NarciFavoriteStarMixin:UpdateStatus(id)
local isFavorite = NarciAnimationInfo.IsFavorite(id);
self:SetVisual(isFavorite);
end
function NarciFavoriteStarMixin:OnClick()
local isFavorite = not self.isFavorite;
self:SetVisual(isFavorite);
local id = AnimationIDEditBox:GetNumber();
if isFavorite then
NarciAnimationInfo.AddFavorite(id);
self:PlayStarAnimation();
else
NarciAnimationInfo.RemoveFavorite(id);
end
Narci_AnimationBrowser:RefreshFavorite(id);
end
function NarciFavoriteStarMixin:OnDoubleClick()
end
-----------------------------------------------------------------------------
function NarciModelControl_PlayAnimationButton_OnClick(self, button)
AnimationIDEditBox:ClearFocus();
local model = ModelFrames[ACTIVE_MODEL_INDEX];
local id = AnimationIDEditBox:GetNumber();
model:PlayAnimation(id);
if button == "LeftButton" then
model:SetPaused(false);
else
PauseAllModel(false);
end
DisablePauseButton();
end
function NarciModelControl_PauseAnimationButton_OnClick(self, button)
AnimationIDEditBox:ClearFocus();
local model = ModelFrames[ACTIVE_MODEL_INDEX]
local id = AnimationIDEditBox:GetNumber();
model:Freeze(id, nil, model.freezedFrame or 0);
if button == "RightButton" then
PauseAllModel(true);
end
DisablePlayButton();
end
local xR, xG, xB = 1, 0, 0; --Spot Light: red, green, blue, stauration
local xHUE = 0;
local xSAT = 0; --Spot Light: stauration
local xBRT = 1; --Spot Light: brightness 100%
local aHue, aSAT, aBRT = 0, 0, 0.8;
local sHue, sSAT, sBRT = 0, 0, 0.8;
local function PlayLightBling(index)
if index == 1 then
BasicPanel.SideView.LightColor.Bling:Play();
BasicPanel.TopView.LightColor.Bling:Play();
else
BasicPanel.SideView.AmbientColor.Bling:Play();
BasicPanel.TopView.AmbientColor.Bling:Play();
end
end
function NarciModelControl_LightSwitch_OnClick(self)
local isAmbientMode = not LightControl.ambientMode;
LightControl.ambientMode = isAmbientMode;
local ColorSliders = BasicPanel.ColorSliders;
local BAK1 = ColorSliders.HueSlider:GetValue();
local BAK2 = ColorSliders.SaturationSlider:GetValue();
local BAK3 = ColorSliders.BrightnessSlider:GetValue();
if isAmbientMode then
sHue = BAK1;
sSAT = BAK2;
sBRT = BAK3;
ColorSliders.HueSlider:SetValue(aHue)
ColorSliders.SaturationSlider:SetValue(aSAT);
ColorSliders.BrightnessSlider:SetValue(aBRT);
PlayLightBling(2)
self.Icon:SetTexCoord(0.25, 0.5, 0, 1);
else
aHue = BAK1;
aSAT = BAK2;
aBRT = BAK3;
ColorSliders.HueSlider:SetValue(sHue)
ColorSliders.SaturationSlider:SetValue(sSAT);
ColorSliders.BrightnessSlider:SetValue(sBRT);
PlayLightBling(1)
self.Icon:SetTexCoord(0, 0.25, 0, 1);
end
end
local CPSA = CreateFrame("Frame"); --Color Pane Switch Animation
CPSA:Hide();
CPSA.t = 0
CPSA.duration = 0.15;
local function ColorPaneSwitchAnim_Update(self, elapsed)
self.t = self.t + elapsed
local height = outSine(self.t, self.StartHeight, self.EndHeight - self.StartHeight, self.duration);
NarciModelControl_BrightnessSlider:SetHeight(height)
if self.t > self.duration then
self:Hide();
end
end
CPSA:SetScript("OnUpdate", ColorPaneSwitchAnim_Update);
CPSA:SetScript("OnHide", function(self)
self.t = 0;
end);
CPSA:SetScript("OnShow", function(self)
self.StartHeight = NarciModelControl_BrightnessSlider:GetHeight();
self.EndHeight = self.EndHeight or 12;
end);
function NarciModelControl_ColorPaneSwitch_OnClick(self)
--local defaultHeight = 278;
self.ShowSlider = not self.ShowSlider;
local state = self:GetParent().ColorPresets:IsShown();
local Colors = self:GetParent().ColorPresets;
local Sliders = self:GetParent().ColorSliders;
if not self.ShowSlider then
--Presets
self.tooltipDescription = L["Show Color Sliders"];
FadeFrame(Sliders, 0.1, 0);
FadeFrame(Colors, 0.1, 1);
self.Icon:SetTexCoord(0, 0.25, 0.25, 0.5);
self:GetParent():SetHitRectInsets(-60, -60, -60, -60);
CPSA:Hide();
CPSA.EndHeight = 0.001;
CPSA:Show();
else
--Sliders
self.tooltipDescription = L["Show Color Presets"];
local ExtraHeight = 12;
FadeFrame(Sliders, 0.1, 1);
FadeFrame(Colors, 0.1, 0);
self.Icon:SetTexCoord(0.75, 1, 0, 0.25);
self:GetParent().padding = ExtraHeight + 40;
CPSA:Hide();
CPSA.EndHeight = ExtraHeight;
CPSA:Show();
end
end
function LightControl:Initialize(newModel)
local model = ModelFrames[ACTIVE_MODEL_INDEX];
local enabled, omni, dirX, dirY, dirZ, ambIntensity, ambR, ambG, ambB, dirIntensity, dirR, dirG, dirB = GetModelLight(model);
SetModelLight(newModel, true, false, dirX, dirY, dirZ, 1, ambR, ambG, ambB, 1, dirR, dirG, dirB);
end
function LightControl:UpdateLight()
local model = ModelFrames[ACTIVE_MODEL_INDEX];
local r, g, b = HSV2RGB(xHUE, xSAT, xBRT);
local _;
if self.linkLight then
if self.ambientMode then
_, _, XdirX, XdirY, XdirZ, _, _, _, _, _, XdirR, XdirG, XdirB = GetModelLight(model);
for i = 1, #ModelFrames do
SetModelLight(ModelFrames[i], true, false, XdirX, XdirY, XdirZ, 1, r, g, b, 1, XdirR, XdirG, XdirB);
end
else
local r0, g0, b0;
_, _, XdirX, XdirY, XdirZ, _, r0, g0, b0, _, XdirR, XdirG, XdirB = GetModelLight(model);
for i = 1, #ModelFrames do
SetModelLight(ModelFrames[i], true, false, XdirX, XdirY, XdirZ, 1, r0, g0, b0, 1, r, g, b);
end
end
else
if self.ambientMode then
_, _, XdirX, XdirY, XdirZ, _, _, _, _, _, XdirR, XdirG, XdirB = GetModelLight(model);
SetModelLight(model, true, false, XdirX, XdirY, XdirZ, 1, r, g, b, 1, XdirR, XdirG, XdirB);
else
local r0, g0, b0;
_, _, XdirX, XdirY, XdirZ, _, r0, g0, b0, _, XdirR, XdirG, XdirB = GetModelLight(model);
SetModelLight(model, true, false, XdirX, XdirY, XdirZ, 1, r0, g0, b0, 1, r, g, b);
end
end
SetLightViewerColor(r, g, b);
end
local function InitializeModelLight(newModel)
local model = ModelFrames[ACTIVE_MODEL_INDEX];
if LINK_LIGHT then
TransitionAPI.SetModelLightFromModel(newModel, model);
end
end
local function SetModelLightColor()
local model = ModelFrames[ACTIVE_MODEL_INDEX];
local r, g, b = HSV2RGB(xHUE, xSAT, xBRT);
local _;
if LINK_LIGHT then
if LightControl.ambientMode then
_, _, XdirX, XdirY, XdirZ, _, _, _, _, _, XdirR, XdirG, XdirB = GetModelLight(model);
for i = 1, #ModelFrames do
SetModelLight(ModelFrames[i], true, false, XdirX, XdirY, XdirZ, 1, r, g, b, 1, XdirR, XdirG, XdirB);
end
else
local r0, g0, b0;
_, _, XdirX, XdirY, XdirZ, _, r0, g0, b0, _, XdirR, XdirG, XdirB = GetModelLight(model);
for i = 1, #ModelFrames do
SetModelLight(ModelFrames[i], true, false, XdirX, XdirY, XdirZ, 1, r0, g0, b0, 1, r, g, b);
end
end
else
if LightControl.ambientMode then
_, _, XdirX, XdirY, XdirZ, _, _, _, _, _, XdirR, XdirG, XdirB = GetModelLight(model);
SetModelLight(model, true, false, XdirX, XdirY, XdirZ, 1, r, g, b, 1, XdirR, XdirG, XdirB);
else
local r0, g0, b0;
_, _, XdirX, XdirY, XdirZ, _, r0, g0, b0, _, XdirR, XdirG, XdirB = GetModelLight(model);
SetModelLight(model, true, false, XdirX, XdirY, XdirZ, 1, r0, g0, b0, 1, r, g, b);
end
end
SetLightViewerColor(r, g, b);
end
function NarciModelControl_HueSlider_OnValueChanged(self, value, isUserInput)
if value ~= self.oldValue then
self.oldValue = value;
xHUE = value;
value = value/60;
if value <= 1 then
xR, xG, xB = 1, value, 0;
elseif value > 1 and value <= 2 then
xR, xG, xB = 2 - value, 1, 0;
elseif value > 2 and value <= 3 then
xR, xG, xB = 0, 1, value - 2;
elseif value > 3 and value <= 4 then
xR, xG, xB = 0, 4 - value, 1;
elseif value > 4 and value <= 5 then
xR, xG, xB = value - 4, 0, 1;
else
xR, xG, xB = 1, 0, 6 - value;
end
SetGradient(NarciModelControl_SaturationSlider.Color, "HORIZONTAL", 1, 1, 1, xR, xG, xB);
SetGradient(NarciModelControl_BrightnessSlider.Color, "HORIZONTAL", 0, 0, 0, xR + (1-xSAT), xG + (1-xSAT), xB + (1-xSAT));
if isUserInput then
SetModelLightColor();
if self:GetParent():IsShown() then
self.Thumb:SetTexCoord(0.96875, 1, 0, 0.0625);
end;
end
end
end
function NarciModelControl_SaturationSlider_OnValueChanged(self, value, isUserInput)
if value ~= self.oldValue then
self.oldValue = value;
xSAT = value;
SetGradient(NarciModelControl_BrightnessSlider.Color, "HORIZONTAL", 0, 0, 0, xR + (1-xSAT), xG + (1-xSAT), xB + (1-xSAT));
if isUserInput then
SetModelLightColor();
if self:GetParent():IsShown() then
self.Thumb:SetTexCoord(0.96875, 1, 0.0625, 0);
end
end
end
end
function NarciModelControl_BrightnessSlider_OnValueChanged(self, value, isUserInput)
if value ~= self.oldValue then
self.oldValue = value;
xBRT = value;
if isUserInput then
SetModelLightColor();
if self:GetParent():IsShown() then
self.Thumb:SetTexCoord(0.96875, 1, 0.0625, 0.125);
end
end
end
end
------------------------------------------------------------
------------------------Actor Panel-------------------------
--Race/gender change, Active Model, Synchronize light/size--
------------------------------------------------------------
local RaceList = {
1, 3, 4, 7, 11, 22,
29, 30, 34, 32, 37, 24,
2, 5, 6, 8, 10, 9,
27, 28, 36, 31, 35, 24,
};
local function SwitchPortrait(index, unit, fromBrowser)
local Portraits = ActorPanel.ActorButton;
local portrait = Portraits["Portrait"..index];
for i = 1, NUM_MAX_ACTORS do
Portraits["Portrait"..i]:Hide();
end
if unit then
SetPortraitTexture(portrait, unit, true);
portrait:SetTexCoord(0, 1, 0, 1);
elseif fromBrowser then
portrait:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Widgets\\ActorPanel\\Dummy.blp");
portrait:SetTexCoord(0, 1, 0, 1);
end
portrait:Show();
end
local function ModelIndexButton_ResetReposition()
--Reset Model Index Buttons' position--
IndexButtonPosition = {
1, 2, 3, 4, 5, 6, 7, 8,
};
local buttons = ActorPanel.ExtraPanel.buttons;
local relativeTo = ActorPanel.ExtraPanel.ReferenceFrame;
local offset;
for i = 1, #buttons do
local button = buttons[i];
button.order = i;
offset = (button.order - 1) * 24; --button width = 24
buttons[i]:ClearAllPoints();
buttons[i]:SetPoint("LEFT", relativeTo, "LEFT", offset, 0);
end
end
local function ResetIndexButton()
local buttons = ActorPanel.ExtraPanel.buttons;
local button = buttons[1];
button.hasModel = true;
button.isModelHidden = false;
button.order = 1;
button.isOn = true;
button.ID:Show();
button.Icon:Hide();
button.Icon:SetTexCoord(0, 0.25, 0, 1);
button:SetModelType("player");
button:SetSelection(true);
for i = 2, #buttons do
button = buttons[i];
button.ID:Hide();
button.Icon:SetTexCoord(0, 0.25, 0, 1);
button.Icon:Show();
button.Border:SetTexCoord(0.875, 1, 0, 0.5)
button:Hide();
button.hasModel = false;
button.isModelHidden = false;
button.isOn = false;
button.Highlight:Hide();
button.order = i;
button:SetSelection(false);
end
buttons[2]:Show();
SwitchPortrait(1);
UpdateActorName(1);
ModelIndexButton_ResetReposition();
end
local function ExitGroupPhoto()
ACTIVE_MODEL_INDEX = 1;
local model = PrimaryPlayerModel;
Narci.ActiveModel = model;
--model:SetActive(true);
model.GroundShadow:Hide();
local panel = ActorPanel;
panel.ExpandButton:Show();
panel.ExpandButton:SetAlpha(1);
panel.ExtraPanel:Hide();
panel.ActorButton.ActorName:SetWidth(96);
local NameFrame = panel.NameFrame;
NameFrame.NameBackground:SetPoint("LEFT", -96, 0);
NameFrame.HiddenFrames:Hide();
local SlotLayerButton = Narci_SlotLayerButton;
SlotLayerButton.isOn = true;
HighlightButton(SlotLayerButton, true);
ModelFrames[1] = PrimaryPlayerModel;
Narci.groupPhotoMode = false;
end
local function ShowIndexButtonLabel(self, bool)
self.Label:SetShown(bool);
self.Status:SetShown(bool);
self.LabelColor:SetShown(bool);
end
local function ShakeModel(model)
local facing = model:GetFacing();
model:SetRotation(facing + 0.07);
After(0.15, function()
model:SetRotation(facing);
end)
end
local function SetModelActive(index)
ACTIVE_MODEL_INDEX = index or 1;
for i = 1, #ModelFrames do
if i ~= ACTIVE_MODEL_INDEX and ModelFrames[i] then
ModelFrames[i]:SetActive(false);
end
end
local model = ModelFrames[ACTIVE_MODEL_INDEX];
if not model then return; end;
Narci.ActiveModel = model;
model:SetActive(true);
model:MakeCurrentCameraCustom();
local shadowFrame = model.GroundShadow;
shadowFrame:EnableMouse(true);
shadowFrame.Option:SetAlpha(1);
shadowFrame.Option:Show();
AnimationIDEditBox:SetAnimationID(model.animationID or 0);
VariationButton:SetVisual(model.variationID or 0);
--Update Virtual Toggle Status
local VirtualToggle = Narci_VirtualActorToggle;
if model:GetModelAlpha() == 1 then
VirtualToggle.isOn = false;
VirtualToggle.Icon:Hide();
else
VirtualToggle.isOn = true;
VirtualToggle.Icon:Show();
end
--Load Spell Visual History
NarciSpellVisualBrowser:LoadHistory();
--Update Play/Pause Button
if model.isPaused then
DisablePlayButton();
NarciModelControl_AnimationSlider:SetValue(model.freezedFrame or 0, true)
else
DisablePauseButton();
end
LightControl:SetLightWidgetFromActiveModel();
if model:IsObjectType("DressUpModel") then
OutfitToggle:EnableButton();
NarciPhotoModeOutfitSelect:SelectPreviewModel(model.buttonIndex);
else
OutfitToggle:DisableButton();
end
end
function Narci_ModelIndexButton_OnClick(self, button)
--Functionality
local unit = "target";
local ID = self:GetID();
local playBling = true;
local model = ModelFrames[ID];
local buttons = self:GetParent().buttons;
if not self.hasModel then
if UnitExists(unit) then
local isPlayer = UnitIsPlayer(unit);
local alternateMode = IsAltKeyDown();
if isPlayer and not alternateMode then
model = _G["NarciPlayerModelFrame"..ID];
else
model = _G["NarciNPCModelFrame"..ID];
end
if not model then
if isPlayer and not alternateMode then
model = CreateFrame("DressUpModel", "NarciPlayerModelFrame"..ID, ModelContainer, "Narci_CharacterModelFrame_Template");
else
model = CreateFrame("CinematicModel", "NarciNPCModelFrame"..ID, ModelContainer, "Narci_NPCModelFrame_Template");
end
model:SetID(ID);
NarciModelControl_AnimationSlider:ResetValueVisual();
end
model.buttonIndex = ID;
model.isPlayer = isPlayer;
model.isVirtual = false;
ModelFrames[ID] = model;
SwitchPortrait(ID, unit);
model.isModelLoaded = false;
SetModelByUnit(model, unit);
model.race, model.gender = InitializePlayerInfo(ID, unit);
ResetModelPosition(model);
InitializeModelLight(model);
self.hasModel = true;
playBling = false;
if buttons[ID + 1] then
buttons[ID + 1]:Show();
end
if isPlayer then
self:SetModelType("player");
NarciPhotoModeOutfitSelect:AddPlayerActor(unit, model);
else
self:SetModelType("npc");
end
--Fix Weapons
After(0, function()
WeaponUpdator:GetTargetWeapons(unit);
end);
else
local PopUp = self:GetParent().PopUp;
PopUp.AddTarget.Text.animError:Play();
Narci:PlayVoice("ERROR");
return;
end
end
model:SetFrameLevel(14 - self.order);
--Visual
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
for i = 1, #buttons do
buttons[i]:SetSelection(i == ID);
end
SwitchPortrait(ID);
UpdateActorName(ID);
--SetGenderIcon(PlayerInfo[ID].gender);
if model then
if button == "LeftButton" then
--Left click to activate model
if not self.isModelHidden then
if playBling then
--give some visual feedback to tell which model has just been activated
ShakeModel(model);
end
local state = true;
model:EnableMouse(state);
model:EnableMouseWheel(state);
model:Show();
self.ID:Show();
self.Icon:Hide();
end
elseif button == "RightButton" then
--Right click to hide model
local state;
if not self.isModelHidden then
state = false;
self.ID:Hide();
self.Icon:SetTexCoord(0.5, 0.75, 0, 1);
self.isModelHidden = true;
self.Status:SetText(L["Hidden"]);
self:SetModelType("hidden");
else
state = true;
self.Icon:SetTexCoord(0.5, 0.75, 0, 1);
self.isModelHidden = false;
self.Status:SetText("");
self:UpdateBorderTexture();
end
model:SetShown(state);
model:EnableMouse(state);
model:EnableMouseWheel(state);
self.ID:SetShown(state);
self.Icon:SetShown(not state);
end
end
SetModelActive(ID);
UpdateGroundShadowOption();
self.isOn = true;
--PopUp Frame
local PopUp = self:GetParent().PopUp;
FadeFrame(PopUp, 0.15, 0);
end
----------------------------------------------------------------------
NarciGenericModelMixin = {};
function NarciGenericModelMixin:SetWidgetType()
if self:GetObjectType() == "DressUpModel" then
self.widgetType = 1;
else
self.widgetType = 2;
end
end
function NarciGenericModelMixin:OnLoad()
table.insert(ModelPool, self);
self.isModelLoaded = false;
self:SetKeepModelOnHide(true);
self.cameraPitch = pi/2;
self.t = 0;
self.cameraDistance = self:GetCameraDistance();
self.rotation = 0.61;
self:SetRotation(self.rotation);
local W = self:GetWidth()
self:SetHitRectInsets(2*W/3 + HIT_RECT_OFFSET, 0, 0, 32.0);
self.AppliedVisuals = {};
self.variationID = 0;
self.animationID = 0;
self:SetWidgetType();
end
function NarciGenericModelMixin:Freeze(animationID, variationID, animationFrame)
if variationID then
self.variationID = variationID;
else
variationID = self.variationID or 0;
end
animationFrame = animationFrame or 0;
self:FreezeAnimation(animationID, variationID, animationFrame);
self.animationID = animationID;
self.isPaused = true;
self.freezedFrame = animationFrame;
end
function NarciGenericModelMixin:PlayAnimation(animationID, variationID)
if variationID then
self.variationID = variationID;
else
variationID = self.variationID or 0;
end
animationID = animationID or 0;
self:SetAnimation(animationID, variationID);
self.animationID = animationID;
self.isPaused = nil;
end
function NarciGenericModelMixin:UpdateVirtualModel()
if self.isVirtual then
After(0, function()
self:SetModelAlpha(0);
end)
end
end
function NarciGenericModelMixin:ResetCameraPosition()
local d = self:GetCameraDistance();
local radian = GLOBAL_CAMERA_PITCH;
self:MakeCurrentCameraCustom();
self.cameraDistance = d;
self.cameraPitch = radian;
SetModelCameraPosition(self, d*sin(radian), 0, d*cos(radian) + 0.8);
TransitionAPI.SetCameraTarget(self, 0, 0, 0.8);
end
function NarciGenericModelMixin:StartPanning()
self.isAltDown = IsAltKeyDown();
self.panning = true;
local posX, posY, posZ = self:GetPosition();
self.posX = posX;
self.posY = posY;
self.posZ = posZ;
local cursorX, cursorY = GetCursorPosition();
self.cursorX = cursorX;
self.cursorY = cursorY;
self.zoomCursorStartX, self.zoomCursorStartY = GetCursorPosition();
end
function NarciGenericModelMixin:OnUpdate()
-- Mouse drag rotation
if (self.mouseDown) then
if ( self.rotationCursorStart ) then
local x, y = GetCursorPosition();
local diffX = (x - self.rotationCursorStart) * 0.01; --MODELFRAME_DRAG_ROTATION_CONSTANT
local diffY = (y - self.cameraPitchCursorStart) * 0.02;
self.rotationCursorStart, self.cameraPitchCursorStart = GetCursorPosition();
if not IsAltKeyDown() then
--Rotate Character
self.rotation = self.rotation + diffX;
if ( self.rotation < 0 ) then
self.rotation = self.rotation + (2 * pi);
end
if ( self.rotation > (2 * pi) ) then
self.rotation = self.rotation - (2 * pi);
end
self:SetRotation(self.rotation, false);
else
--Rotate Camera (pitch)
self.cameraPitch = self.cameraPitch + diffY;
if ( self.cameraPitch <= (0 + 0.01)) then
self.cameraPitch = 0.01;
end
if ( self.cameraPitch >= ( pi - 0.01)) then
self.cameraPitch = pi - 0.01;
end
if self.isVirtual then
UpdateCameraPitch(self, self.cameraPitch);
else
UpdateGlobalCameraPitch(self.cameraPitch);
end
end
end
elseif ( self.panning ) then
local isAltDown = IsAltKeyDown();
if isAltDown ~= self.isAltDown then
--Reset cursor positions
self:StartPanning();
end
local modelScale = self:GetModelScale();
local cursorX, cursorY = GetCursorPosition();
local scale = UIParent:GetEffectiveScale();
local diff = (cursorX - self.zoomCursorStartX) + (cursorY - self.zoomCursorStartY);
self.zoomCursorStartX, self.zoomCursorStartY = GetCursorPosition();
if not isAltDown then
local settings = ModelSettings["Generic"];
local zoom = sqrt(sqrt(self.cameraDistance));
local transformationRatio = 0.00002*settings.panValue * 2 ^ (zoom * 2) * scale / modelScale;
local dx = (cursorX - self.cursorX) * transformationRatio;
local dy = (cursorY - self.cursorY) * transformationRatio;
local posY = self.posY + dx;
local posZ = self.posZ + dy;
self:SetPosition(self.posX, posY, posZ);
--print("Y: "..posY.." Z: "..posZ.." Dis: "..self.cameraDistance)
else
if LINK_SCALE then
for i = 1, #ModelFrames do
--ModelFrames[i]:SetCameraDistance(Value);
ModelFrames[i].cameraDistance = self.cameraDistance - diff * 0.01;
UpdateCameraPosition(ModelFrames[i]);
end
else
self.cameraDistance = self.cameraDistance - diff * 0.01;
UpdateCameraPosition(self);
end
end
end
end
function NarciGenericModelMixin:OnMouseWheel(delta)
if not self:HasCustomCamera() then return; end
SmoothZoomModel(self.cameraDistance - delta * 0.25);
end
function NarciGenericModelMixin:OnMouseUp(button)
if ( button == "RightButton" and self.panning ) then
self.panning = false;
elseif ( self.mouseDown ) then
if ( not button or button == "LeftButton" ) then
self.mouseDown = false;
end
end
end
function NarciGenericModelMixin:OnMouseDown(button)
if ( button == "RightButton" and not self.mouseDown ) then
self:StartPanning();
elseif button == "LeftButton" then
self.mouseDown = true;
self.rotationCursorStart, self.cameraPitchCursorStart = GetCursorPosition();
elseif button == "MiddleButton" then
if IsAltKeyDown() then
ResetAllCameraPitch();
end
end
end
function NarciGenericModelMixin:OnHide()
if ( self.panning ) then
self.panning = false;
end
self.mouseDown = false;
end
local function RedressPlayerAfterLoading(model)
if model:IsObjectType("DressUpModel") and model.customTransmogList then
After(0, function()
model:Undress();
local mainHandInfo, offHandInfo; --a workaround cuz there seems to be a delay before weapons being loaded
for slotID, transmogInfo in pairs(model.customTransmogList) do
if slotID == 16 then
mainHandInfo = transmogInfo;
elseif slotID == 17 then
offHandInfo = transmogInfo;
else
model:SetItemTransmogInfo(transmogInfo, slotID);
end
After(0.1, function()
model:UndressSlot(16);
model:UndressSlot(17);
model:SetItemTransmogInfo(mainHandInfo, 16);
model:SetItemTransmogInfo(offHandInfo, 17);
end);
end
end);
end
end
function NarciGenericModelMixin:OnModelLoaded()
InitializeModel(self);
self:UpdateVirtualModel();
self.isModelLoaded = true;
self.isAnimationCached = nil;
self.animationList = {};
RedressPlayerAfterLoading(self);
end
function NarciGenericModelMixin:OnAnimFinished()
--Disabled because unsheathing weapon will stop animation from playing
if LOOP_ANIMATION and self.animationID and not self.isPaused then
local id = self.animationID;
if id ~= 0 and id ~= 804 and id ~= 808 then
self:SetAnimation(self.animationID, self.variationID or 0);
end
end
end
local inventoryTypeSlot = {
--Mainhand~1 Offhand~2
INVTYPE_SHIELD = 2,
INVTYPE_RANGED = 2, --Bow
INVTYPE_RANGEDRIGHT = 1, --Crossbow/Gun
INVTYPE_2HWEAPON = 1,
INVTYPE_WEAPONMAINHAND = 1,
INVTYPE_WEAPONOFFHAND = 2,
INVTYPE_THROWN = 1,
INVTYPE_RELIC = 2,
};
local function RedirectInventorySlot(itemID, widgetType)
local _, _, _, itemEquipLoc, _, itemClassID, itemSubClassID = C_Item.GetItemInfoInstant(itemID);
if itemClassID == 4 and itemSubClassID == 6 then --shield ~ always offhand
return 2
elseif widgetType == 2 then --CinematicModel
return inventoryTypeSlot[itemEquipLoc]
end
end
function NarciGenericModelMixin:EquipWeapon(itemID, sourceID, hand)
--item: "item:123456"(string) or sourceID(number)
--print(string.format("item: %s source: %s", itemID, sourceID));
if not self.equippedWeapons then
self.equippedWeapons = {};
end
self.holdWeapon = true;
--redirect hand
hand = RedirectInventorySlot(itemID, self.widgetType) or hand;
local slotID;
local itemTryOnResult;
if hand and hand == 2 then
--offhand
slotID = 17;
if self.SetItemTransmogInfo then
if sourceID and sourceID ~= 0 then
itemTryOnResult = self:EquipItemBySourceID(sourceID, 17);
else
self:UndressSlot(17);
end
self.equippedWeapons[2] = sourceID;
elseif self.TryOn then
if sourceID and sourceID ~= 0 then
itemTryOnResult = self:TryOn(sourceID, "SECONDARYHANDSLOT");
else
self:UndressSlot(17);
end
self.equippedWeapons[2] = sourceID;
elseif self.EquipItem then
local noMainHand = not self.equippedWeapons[1];
if noMainHand then
self:EquipItem(itemID);
self:EquipItem(itemID);
self:EquipItem(111532); --Remove mainhand
else
self:EquipItem(130105); --Invisible Holdable
self:EquipItem(itemID);
end
self.equippedWeapons[2] = itemID;
itemTryOnResult = 0;
end
else
--mainhand
slotID = 16;
if self.SetItemTransmogInfo then
if sourceID and sourceID ~= 0 then
itemTryOnResult = self:EquipItemBySourceID(sourceID, 16);
else
self:UndressSlot(16);
end
self.equippedWeapons[1] = sourceID;
elseif self.TryOn then
if sourceID and sourceID ~= 0 then
itemTryOnResult = self:TryOn(sourceID, "MAINHANDSLOT");
else
self:UndressSlot(16);
end
self.equippedWeapons[1] = sourceID;
elseif self.EquipItem then
--self:UnequipItems(); --Doesn't work
self:EquipItem(111532); --Invisible Mainhand
self:EquipItem(itemID);
self.equippedWeapons[1] = itemID;
itemTryOnResult = 0;
end
end
if self.customTransmogList and sourceID then
self.customTransmogList[slotID] = ItemUtil.CreateItemTransmogInfo(sourceID);
end
return (itemTryOnResult == 0), hand, self.widgetType --ItemTryOnReason.Success ~ 0
end
function NarciGenericModelMixin:ReEquipWeapons()
if self.equippedWeapons then
if self.SetItemTransmogInfo then
local weaponID = self.equippedWeapons[1];
if weaponID then
self:EquipItemBySourceID(weaponID, 16);
end
weaponID = self.equippedWeapons[2];
if weaponID then
self:EquipItemBySourceID(weaponID, 17);
end
elseif self.TryOn then
local weaponID = self.equippedWeapons[1];
if weaponID then
self:TryOn(weaponID, "MAINHANDSLOT");
end
weaponID = self.equippedWeapons[2];
if weaponID then
self:TryOn(weaponID, "SECONDARYHANDSLOT");
end
else
--CinematicModel
if self.holdWeapon then
local itemID = self.equippedWeapons[1];
if itemID then
self:EquipItem(itemID);
end
itemID = self.equippedWeapons[2];
if itemID then
self:EquipItem(itemID);
end
end
end
end
end
function NarciGenericModelMixin:SetActive(state)
if state then
self:SetScript("OnUpdate", self.OnUpdate);
if self.isItemLoaded then
Narci_PhotoModeWeaponFrame:SetItemFromActor(self);
else
After(0.5, function()
Narci_PhotoModeWeaponFrame:SetItemFromActor(self);
end);
end
Narci_WeaponBrowser:ChangeActiveModelType(self.widgetType);
else
self:SetScript("OnUpdate", nil);
self.GroundShadow.Option:Hide();
end
self.GroundShadow:EnableMouse(state);
self:EnableMouse(state);
self:EnableMouseWheel(state);
end
function NarciGenericModelMixin:EquipItemBySourceID(sourceID, slotID)
if sourceID and sourceID ~= 0 and self.SetItemTransmogInfo then
local itemTransmogInfoMixin = CreateFromMixins(ItemTransmogInfoMixin);
itemTransmogInfoMixin:Init(sourceID);
local result = self:SetItemTransmogInfo(itemTransmogInfoMixin, slotID);
return result
end
end
--------------------------------------------------------------------------------
NarciMainModelMixin = CreateFromMixins(NarciGenericModelMixin);
function NarciMainModelMixin:OnLoad()
table.insert(ModelPool, self);
self.isVirtual = false;
self.isModelLoaded = false;
SetModelByUnit(self, "player");
self.mouseDown = false;
self.panning = false;
self.cameraPitch = pi/2;
SetModelLight(self, true, false, cos(pi/4)*sin(-pi/4) , cos(pi/4)*cos(-pi/4) , -cos(pi/4), 1, 0.8, 0.8, 0.8, 1, 0.8, 0.8, 0.8);
self.t = 0;
self.buttonIndex = 1;
local defaultRotation = 0.61;
self:SetRotation(defaultRotation);
self.rotation = defaultRotation;
local r, g, b = 0, 177/255, 64/255;
FullSceenChromaKey = Narci_ChromaKey;
FullSceenChromaKey:SetColorTexture(r, g, b);
FullScreenAlphaChannel = Narci_FullScreenAlphaChannel;
local W = self:GetWidth();
self:SetHitRectInsets(2*W/3 + HIT_RECT_OFFSET, 0, 0, 32.0);
ModelFrames[1] = self;
PrimaryPlayerModel = self;
Narci.ActiveModel = self;
self.AppliedVisuals = {};
self.animationID = 0;
self.variationID = 0;
self:SetWidgetType();
end
function NarciMainModelMixin:OnMouseUpModified(button)
self:OnMouseUp(button);
self.GuideLineCenter:Hide();
end
function NarciMainModelMixin:OnMouseDownModified(button)
self:OnMouseDown(button)
if self.GuideFrame:IsVisible() then
self.GuideLineCenter:Show();
end
end
function NarciMainModelMixin:OnModelLoaded()
self:MakeCurrentCameraCustom();
self.isModelLoaded = true;
self.isAnimationCached = nil;
self.animationList = {};
RedressPlayerAfterLoading(self);
end
----------------------------------------------------------------------
NarciPhotoModeAPI = {};
local function CreateEmptyModelForNPCBrowser(actorIndex, isPet)
local ID = actorIndex;
local buttons = ActorPanel.ExtraPanel.buttons;
local IndexButton = buttons[ID];
if not ID or not IndexButton then return; end;
local model = _G["NarciNPCModelFrame"..ID];
if not model then
model = CreateFrame("CinematicModel", "NarciNPCModelFrame"..ID, ModelContainer, "Narci_NPCModelFrame_Template");
model:SetID(ID);
end
--model:SetModel(124640);
model.isLoaded = false;
model.isPlayer = false;
ModelFrames[ID] = model;
model.buttonIndex = ID;
model:SetShown(true);
model:EnableMouse(true);
model:EnableMouseWheel(true);
model:SetFrameLevel(14 - IndexButton.order);
ResetModelPosition(model);
InitializeModelLight(model);
model.race, model.gender = InitializePlayerInfo(ID, "player");
UpdateActorName(ID);
--SetGenderIcon(PlayerInfo[ID].gender);
IndexButton.hasModel = true;
IndexButton.ID:Show();
IndexButton.Icon:Hide();
IndexButton.Label:SetText(" ");
if isPet then
IndexButton:SetModelType("pet");
else
IndexButton:SetModelType("npc");
end
model:SetModelAlpha(1);
model.isVirtual = false;
for i= 1, #buttons do
buttons[i]:SetSelection(i == ID);
end
if buttons[ID + 1] then
buttons[ID + 1]:Show();
end
SwitchPortrait(ID, nil, true)
SetModelActive(ID);
UpdateGroundShadowOption();
return model
end
NarciPhotoModeAPI.CreateEmptyModelForNPCBrowser = CreateEmptyModelForNPCBrowser;
local function OverrideActorInfo(actorIndex, name, hasWeapon, portraitFile)
if not PlayerInfo[actorIndex] then
PlayerInfo[actorIndex] = {};
local info = PlayerInfo[actorIndex];
info.raceID_Original = 1;
info.raceID = 1;
info.gender_Original = 2;
info.gender = 2;
info.class = "PRIEST";
end
PlayerInfo[actorIndex].name = name;
--ActorPanel.ExtraPanel.buttons[actorIndex].Label:SetText(name);
--ActorPanel.ActorButton.ActorName:SetText(name);
SmartSetActorName(ActorPanel.ExtraPanel.buttons[actorIndex].Label, name);
SmartSetActorName(ActorPanel.ActorButton.ActorName, name);
--Weapon
--Portrait
if portraitFile then
local Portraits = ActorPanel.ActorButton;
local Portrait = Portraits["Portrait"..actorIndex];
Portrait:SetTexture(portraitFile);
if type(portraitFile) ~= "number" then
Portrait:SetTexCoord(0.734, 0.472, 0, 0.52);
end
end
end
NarciPhotoModeAPI.OverrideActorInfo = OverrideActorInfo;
local function CreateAndSelectNewActor(actorIndex, unit, isVirtual)
local ID = actorIndex;
local buttons = ActorPanel.ExtraPanel.buttons;
local IndexButton = buttons[ID];
if not ID or not IndexButton then return; end;
local model;
local inputType = type(unit);
local alternateMode = IsAltKeyDown();
if inputType == "string" then
--Create from unit (player/target/party)
if UnitExists(unit) then
if alternateMode then
model = _G["NarciNPCModelFrame"..ID];
else
model = _G["NarciPlayerModelFrame"..ID];
end
end
if not model then
if alternateMode and not isVirtual then
model = CreateFrame("CinematicModel", "NarciNPCModelFrame"..ID, ModelContainer, "Narci_NPCModelFrame_Template");
else
model = CreateFrame("DressUpModel", "NarciPlayerModelFrame"..ID, ModelContainer, "Narci_CharacterModelFrame_Template");
end
model:SetID(ID);
NarciModelControl_AnimationSlider:ResetValueVisual();
end
model.isModelLoaded = false;
SetModelByUnit(model, unit);
model.isPlayer = true;
NarciPhotoModeOutfitSelect:AddPlayerActor(unit, model);
elseif inputType == "number" then
--Create from displayID
model = _G["NarciNPCModelFrame"..ID];
if not model then
model = CreateFrame("CinematicModel", "NarciNPCModelFrame"..ID, ModelContainer, "Narci_NPCModelFrame_Template");
model:SetID(ID);
end
alternateMode = true;
model.isModelLoaded = false;
model:SetDisplayInfo(unit);
model.isPlayer = false;
unit = "player";
else
return;
end
ModelFrames[ID] = model;
model.buttonIndex = ID;
model:SetShown(true);
model:SetFrameLevel(14 - IndexButton.order);
ResetModelPosition(model);
InitializeModelLight(model);
SwitchPortrait(ID, unit); --Use diffrent portrait for virtual actor?
model.race, model.gender = InitializePlayerInfo(ID, unit);
UpdateActorName(ID);
--SetGenderIcon(PlayerInfo[ID].gender);
--Update index button
IndexButton.hasModel = true;
IndexButton.ID:Show();
IndexButton.Icon:Hide();
if isVirtual then
IndexButton:SetModelType("virtual");
model:SetModelAlpha(0)
model.isVirtual = true;
PlayerInfo[ID].name = "|cff0081a9"..VIRTUAL_ACTOR.."|r";
IndexButton.Label:SetText(VIRTUAL_ACTOR);
IndexButton.Label:SetTextColor(0, 0.505, 0.663);
else
if model.isPlayer then
IndexButton:SetModelType("player");
else
IndexButton:SetModelType("npc");
end
model:SetModelAlpha(1)
model.isVirtual = false;
end
for i= 1, #buttons do
buttons[i]:SetSelection(i == ID);
end
if buttons[ID + 1] then
buttons[ID + 1]:Show();
end
SetModelActive(ID);
UpdateGroundShadowOption();
model.creatureID = nil;
model.displayID = nil;
WeaponUpdator:GetTargetWeapons(unit);
end
function Narci_ModelIndexButton_AddSelf(self)
local PopUp = self:GetParent();
local index = PopUp.Index;
CreateAndSelectNewActor(index, "player", false);
FadeFrame(PopUp, 0.15, 0);
end
function Narci_ModelIndexButton_AddVirtual(self)
local PopUp = self:GetParent();
local index = PopUp.Index;
CreateAndSelectNewActor(index, "player", true);
FadeFrame(PopUp, 0.15, 0);
end
local function ModelIndexButton_ShowSelfLabelAndHideOthers(self)
local buttons = self:GetParent().buttons;
local button;
for i = 1, #buttons do
button = buttons[i];
ShowIndexButtonLabel(button, false);
end
ShowIndexButtonLabel(self, true);
end
local function UpdateButtonOrder(button, newOrder)
local buttons = ActorPanel.ExtraPanel.buttons;
local buttonID = button:GetID();
local orderTable = {};
for i = 1, #IndexButtonPosition do
if IndexButtonPosition[i] == buttonID then
IndexButtonPosition[i] = false;
end
end
local a = 1;
for i = 1, #IndexButtonPosition do
if IndexButtonPosition[i] then
if a == newOrder then
a = a + 1;
end
orderTable[a] = IndexButtonPosition[i];
a = a + 1;
end
end
orderTable[newOrder] = buttonID;
--[[
local str = "";
for i = 1, 5 do
if orderTable[i] then
str = str..orderTable[i].." ";
else
return;
end
end
print(str);
--]]
return orderTable;
end
function Narci_ModelIndexButton_AnimFrame_OnUpdate(self, elapsed)
self.t = self.t + elapsed;
local value = outSine(self.t, self.StartX, self.EndX - self.StartX, self.duration) --0.11 NE
self:GetParent():SetPoint("LEFT", self.relativeTo, "LEFT", value, 0);
if self.t >= self.duration then
self:Hide();
end
end
local function AssignOrder(orderTable)
--Replace Index Button (transition animation)--
if not orderTable then return; end;
local buttons = ActorPanel.ExtraPanel.buttons;
local button, buttonID, model;
local offset;
for i = 1, #orderTable do
buttonID = orderTable[i];
button = buttons[buttonID];
button.order = i;
model = ModelFrames[buttonID];
if model then
model:SetFrameLevel(14 - i);
--print( (model:GetName()).. " Level ".. (14-i) )
end
offset = 24*(i - 1);
button.AnimFrame:Hide();
button.AnimFrame.EndX = 24*(i - 1);
button.AnimFrame:Show();
end
end
-------------------------------------------------------
function Narci_VirtualActorToggle_OnClick(self)
self.isOn = not self.isOn;
local IndexButton = ActorPanel.ExtraPanel.buttons[ACTIVE_MODEL_INDEX];
local model = ModelFrames[ACTIVE_MODEL_INDEX];
if self.isOn then
self.Icon:Show();
IndexButton:SetModelType("virtual");
model:SetModelAlpha(0)
model.isVirtual = true;
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
else
self.Icon:Hide();
model:SetModelAlpha(1)
model.isVirtual = false;
IndexButton:UpdateBorderTexture();
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF);
end
end
-------------------------------------------------------
function Narci_ExtraPanel_OnLoad(self)
local buttons = {};
for i = 1, NUM_MAX_ACTORS do
local button = CreateFrame("Button", nil, self, "Narci_ModelIndexButton_Template");
button:SetID(i);
if i == 1 then
button:SetPoint("LEFT", self.ReferenceFrame, "LEFT", 0, 0);
else
button:SetPoint("LEFT", buttons[i - 1], "RIGHT", 0, 0);
end
button:RegisterForDrag("LeftButton");
button:SetModelType("player");
button.order = self:GetID();
button.isOn = false;
button.lockHighlight = false;
button.ID:SetText(i);
button.AnimFrame.relativeTo = self.ReferenceFrame;
tinsert(buttons, button);
end
self.buttons = buttons;
end
NarciIndexRepositionFrameMixin = {};
function NarciIndexRepositionFrameMixin:OnLoad()
self.orderTable = {};
self.ref = self:GetParent().ReferenceFrame;
end
function NarciIndexRepositionFrameMixin:OnShow()
self.x0 = self:GetParent().ReferenceFrame:GetLeft();
self.order = nil;
self.xmin = self.x0 + 0.1 + 12;
self.xmax = self.x0 + (NUM_MAX_ACTORS - 1) * 24 + 12; -- Index Button Width numMaxButton - 1
self.scale = self:GetEffectiveScale() or 1;
end
function NarciIndexRepositionFrameMixin:OnUpdate(elapsed)
--drag an index button to replace model's framelevel--
local xpos, _ = GetCursorPosition();
xpos = xpos / self.scale;
local buttons = self:GetParent().buttons;
local ofsx, order;
if xpos <= self.xmin then
ofsx = 0 + 12;
elseif xpos >= self.xmax then
ofsx = (NUM_MAX_ACTORS - 1) * 24 + 12;
else
ofsx = (xpos - self.x0);
end
local button = buttons[self.ActiveButton];
for i = 1, NUM_MAX_ACTORS do
if ofsx > 24*(i - 1) and ofsx <= 24*i then
if self.order ~= i then
self.order = i;
self.orderTable = UpdateButtonOrder(button, self.order);
AssignOrder(self.orderTable);
end
break;
end
end
--print(ofsx);
button:ClearAllPoints();
button:SetPoint("CENTER", self.ref, "LEFT", ofsx, 0);
end
function NarciIndexRepositionFrameMixin:OnHide()
IndexButtonPosition = CopyTable(self.orderTable) or IndexButtonPosition;
AssignOrder(IndexButtonPosition);
end
local function RemoveActor(actorIndex)
local ID, model;
if actorIndex then
ID = actorIndex;
model = _G["NarciNPCModelFrame"..ID];
else
ID = ACTIVE_MODEL_INDEX;
model = ModelFrames[ID];
end
local buttons = ActorPanel.ExtraPanel.buttons;
local button = buttons[ID];
if model then
model.isModelLoaded = false;
model.isItemLoaded = false;
model:ClearModel();
model.isVirtual = false;
model.isCameraDirty = true;
model:Hide();
model.creatureID = nil;
model.displayID = nil;
model.creatureName = nil;
model.equippedWeapons = nil;
model.isAnimationCached = nil;
model.animationList = {};
model.customTransmogList = nil;
model.GroundShadow:Hide();
model.freezedFrame = 0;
model.animationID = nil;
wipe(model.AppliedVisuals);
end
button:SetModelType("empty");
button.hasModel = false;
button.isModelHidden = false;
button.isOn = false;
button.Icon:SetTexCoord(0, 0.25, 0, 1);
button.Icon:Show();
button.ID:Hide();
button.Highlight:Hide();
for i = ID - 1, 1, -1 do
if buttons[i].hasModel then
buttons[i]:Click();
return;
end
end
for i = ID + 1, #buttons do
if buttons[i].hasModel then
buttons[i]:Click();
return;
end
end
end
NarciPhotoModeAPI.RemoveActor = RemoveActor;
function Narci_DeleteModelButton_OnClick()
RemoveActor();
end
function Narci_LinkLightButton_OnClick(self)
self.isOn = not self.isOn;
LINK_LIGHT = self.isOn;
HighlightButton(self, self.isOn, true);
self.ClipFrame.LinkButton:Click();
--self.LinkButton.FadeOut:Play();
end
function Narci_LinkScaleButton_OnClick(self)
self.isOn = not self.isOn;
LINK_SCALE = self.isOn;
HighlightButton(self, self.isOn, true);
self.ClipFrame.LinkButton:Click();
--self.LinkButton.FadeOut:Play();
end
function Narci_ActorButton_OnClick(self)
self.isOn = not self.isOn;
if self.isOn then
self:LockHighlight();
AutoCloseRaceOption(4);
FadeFrame(Narci_RaceOptionFrame, 0.2, 1);
else
self:UnlockHighlight();
FadeFrame(Narci_RaceOptionFrame, 0.2, 0);
end
WidgetTooltip:HideTooltip();
end
local function HideGroundShadowControl()
local model;
for i = 1, #ModelFrames do
model = ModelFrames[i];
if model then
model.GroundShadow.Option:Hide();
end
end
end
function Narci_GroundShadowToggle_ResetButton_OnClick(self)
local frame = ModelFrames[ACTIVE_MODEL_INDEX].GroundShadow;
frame:ClearAllPoints();
frame:SetPoint("BOTTOM", UIParent, "BOTTOM", 0 ,0);
frame:SetUserPlaced(false);
frame.Option.SizeSlider:SetValue(1);
frame.Option.AlphaSlider:SetValue(1);
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF);
end
function Narci_GroundShadowToggle_OnHide(self)
HideGroundShadowControl();
self.isOn = false;
HighlightButton(self, false);
end
function Narci_GroundShadowToggle_OnClick(self)
local frame = ModelFrames[ACTIVE_MODEL_INDEX].GroundShadow;
local state = not frame:IsShown();
frame:SetShown(state);
self.isOn = state;
UpdateGroundShadowOption();
end
local function CreateRaceButtonList(self, buttonTemplate, buttonNameTable, numRow)
local button, buttonWidth, buttonHeight;
local buttons, columnWidth = {}, {};
local parentName = self:GetName();
local buttonName = parentName and (parentName .. "Button") or nil;
local minWidth, maxWidth = 80, 0;
local GetRaceInfo = C_CreatureInfo.GetRaceInfo;
local _, _, playerRaceID = UnitRace("player");
playerRaceID = playerRaceID or -1;
local column = 1;
local insetFrame = self.Inset;
local initialPoint = "TOPLEFT";
local initialRelative = "TOPLEFT";
local initialOffsetX = 0;
local initialOffsetY = 0;
local point = "TOPLEFT";
local relativePoint = "BOTTOMLEFT";
local offsetX = 0;
local offsetY = 0;
local numButtons = #buttonNameTable;
local totalHeight = 0;
numRow = numRow or numButtons;
local value;
for i = 1, numButtons do
button = CreateFrame("BUTTON", buttonName and (buttonName .. i) or nil, self, buttonTemplate);
value = buttonNameTable[i]
if value ~= -1 then
button:SetID(value);
button.Name:SetText(GetRaceInfo(value).raceName);
if value == playerRaceID then
button.Name:SetTextColor(0.25, 0.78, 0.92);
--highlight the original race
end
else
--Create placeholder
button.Name:SetText("");
button:Disable();
end
if i == 1 then
button:SetPoint(initialPoint, insetFrame, initialRelative, initialOffsetX, initialOffsetY);
buttonHeight = button:GetHeight();
totalHeight = buttonHeight * numRow;
else
if i % numRow == 1 then
button:SetPoint(point, buttons[i- numRow], "TOPRIGHT", offsetX, offsetY);
column = column + 1;
maxWidth = 0;
--Create divider
local tex;
if column == 3 then
tex = self:CreateTexture(nil, "OVERLAY", nil, 1);
tex:SetSize(0.5, 0);
tex:SetColorTexture(1, 1, 1, 0.15);
tex:SetPoint("TOP", button, "TOPLEFT", 0, -2);
tex:SetPoint("BOTTOM", insetFrame, "BOTTOM", 0, 2);
end
if (column - 1) % 2 == 1 then
tex = self:CreateTexture(nil, "ARTWORK", nil, 1);
tex:SetSize(totalHeight + 22, totalHeight + 22);
tex:SetPoint("TOPRIGHT", button, "TOPRIGHT", 5, 12);
--tex:SetWidth(totalHeight - 10);
tex:SetTexture("Interface/AddOns/Narcissus/Art/Widgets/LightSetup/FactionEmblems.tga")
tex:SetAlpha(0.15);
if column == 2 then
tex:SetTexCoord(0, 0.5, 0, 1);
elseif column == 4 then
tex:SetTexCoord(0.5, 1, 0, 1);
end
end
else
button:SetPoint(point, buttons[i- 1], relativePoint, offsetX, offsetY);
button:SetPoint("TOPRIGHT", buttons[i- 1], "TOPRIGHT", 0, 0);
end
end
if column < 3 then
--Alliance blue
button.Background:SetColorTexture(10/255, 40/255, 120/255, 0.2);
else
--Horde red
button.Background:SetColorTexture(120/255, 27/255, 27/255, 0.2);
end
buttonWidth = button.Name:GetWidth();
if buttonWidth > maxWidth then
maxWidth = buttonWidth;
end
columnWidth[column] = math.max(minWidth, math.floor(maxWidth + 0.5 + 16));
tinsert(buttons, button);
end
local totalWidth = 0;
for i = 1, column do
--Resize Button
buttons[(i-1)*numRow + 1]:SetWidth(columnWidth[i]);
totalWidth = totalWidth + columnWidth[i];
end
self:SetSize(totalWidth + 10, numRow*buttonHeight + 10)
self.buttons = buttons;
end
local function CacheModel()
local model = PrimaryPlayerModel;
SetModelByUnit(model, "player");
WeaponUpdator:GetPlayerWeapons("player");
model:SetAlpha(0);
model:Show();
model:SetPosition(0, -1000, -2200)
model:EnableMouse(false)
model:EnableMouseWheel(false)
After(0.5, function()
model:Hide();
model:EnableMouse(true);
model:EnableMouseWheel(true);
model:SetScript("OnShow", Narci_CharacterModelFrame_OnShow);
end)
end
---------------------------------------------------------------------------
--Expand Animation
local FRAME_GAP = 0.0166; --60FPS
local AnimationInfo = {
frames = 26,
cX = 0.4296875,
cY = 0.056640625,
colum = 2,
row = 17,
};
local function AnimationSequence_OnUpdate(self, elapsed)
self.t = self.t + elapsed;
if self.t >= FRAME_GAP then
self:SetAlpha(1);
self.i = self.i + math.floor(self.t / FRAME_GAP);
self.t = 0;
local alpha = 0;
if self.i >= AnimationInfo.frames then
self.i = AnimationInfo.frames;
self.isPlaying = nil;
alpha = 1;
elseif self.i >= 20 then
alpha = (self.i - 20) / 6;
end
self:SetSubFrameAlpha(alpha);
local col = math.ceil(self.i / AnimationInfo.row);
local row = self.i + (1 - col) * AnimationInfo.row;
local left, right = (col -1) * AnimationInfo.cX, col * AnimationInfo.cX;
local top, bottom = (row -1) * AnimationInfo.cY, row * AnimationInfo.cY;
self.SequenceTexture:SetTexCoord(left, right, top, bottom);
if not self.isPlaying then
self:StopAnimation();
end
end
end
local ExpandAnim = CreateFrame("Frame"); --name frame moves to the right
ExpandAnim:Hide();
ExpandAnim.t = 0;
ExpandAnim:SetScript("OnShow", function(self)
self.d = 0.5;
self.t = 0;
self.tex = ActorPanel.NameFrame.NameBackground;
end)
ExpandAnim:SetScript("OnUpdate", function(self, elapsed)
self.t = self.t + elapsed;
local offset = outSine(self.t, -96, 95, self.d);
if self.t >= self.d then
offset = -1;
self:Hide();
end
self.tex:SetPoint("LEFT", offset, 0);
end)
NarciPhotoModeExtraPanelMixin = {};
function NarciPhotoModeExtraPanelMixin:StopAnimation()
self:SetScript("OnUpdate", nil);
end
function NarciPhotoModeExtraPanelMixin:ShowFrame()
self.i = 0;
self.t = FRAME_GAP;
self.isPlaying = true;
self:SetScript("OnUpdate", AnimationSequence_OnUpdate);
self:Show();
self:SetAlpha(0);
self:SetSubFrameAlpha(0);
end
function NarciPhotoModeExtraPanelMixin:SetSubFrameAlpha(alpha)
self.buttons[1]:SetAlpha(alpha);
self.buttons[2]:SetAlpha(alpha);
self.ArtFrame:SetAlpha(alpha);
end
function Narci_GroupPhotoToggle_OnClick(self)
ResetIndexButton();
--SetModelActive(1);
local ExtraPanel = ActorPanel.ExtraPanel;
ActorPanel.ActorButton.ActorName:SetWidth(120);
FadeIn(ActorPanel.NameFrame.HiddenFrames, 0.5);
ExpandAnim:Show();
ExtraPanel:ShowFrame();
After(0, function()
self:Hide();
end)
if Narci_SlotLayerButton.isOn then
Narci_SlotLayerButton:Click();
end
Narci.showExitConfirm = true;
Narci_NPCBrowser:Init();
Narci.groupPhotoMode = true;
NarciScreenshotToolbar:ShowUI("PhotoMode");
end
----------------------------------------------------
NarciShadowRotationMixin = {};
function NarciShadowRotationMixin:OnLoad()
local parent = self:GetParent();
local GroundShadowContainer = parent:GetParent().ShadowTextures;
local shadow = GroundShadowContainer.RadialShadow;
local shadowMask = GroundShadowContainer.RadialShadowMask;
local defaultRadian = 0;
local defaultRadius = 72;
local rMin, rMax = 40, 120;
local scaleMin, scaleMax = 0.25, 1.25;
self.lastRadiant = 0;
local function FlipShadowMask(direction)
if direction >= 0 then
shadowMask:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Widgets\\LightSetup\\GroundShadowRadial-Mask-Up");
else
shadowMask:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Widgets\\LightSetup\\GroundShadowRadial-Mask-Down");
end
end
function self:UpdatePosition(radian, r, initialized)
local dR = r / rMax / 2;
self.Shaft:SetTexCoord(0.5 - dR, 0.5 + dR, 0, 1);
local d = 2 * r;
self.Shaft:SetSize(d, 6);
self.RingMask1:SetSize(d - 1, d - 1);
self.RingMask2:SetSize(d + 1, d + 1);
self.Shaft:SetRotation(radian);
self.DashedLine:SetRotation(radian);
shadow:SetRotation(radian);
local scale = 0.0125 * r - 0.25;
--shadow:SetScale(0.0125 * r - 0.25);
shadow:SetWidth(800* scale + 0.5);
self:SetPoint("CENTER", parent, "CENTER", r * cos(radian), r * sin(radian));
if radian > 0 and self.lastRadiant < 0 then
FlipShadowMask(1);
elseif radian < 0 and self.lastRadiant > 0 then
FlipShadowMask(-1);
end
self.lastRadiant = radian;
--Update Light Control Button
if (not initialized) and (GroundShadowContainer.controlLights) then
LightControl:SetDirection(pi + radian, 1 - 2*dR);
end
end
local UpdateFrame = CreateFrame("Frame", nil, self);
self.UpdateFrame = UpdateFrame;
UpdateFrame:Hide();
UpdateFrame:SetScript("OnHide", function(frame)
frame:Hide();
end)
UpdateFrame:SetScript("OnUpdate", function()
local px, py = GetCursorPosition();
local dx = (px + self.dx) / self.scale - self.cx;
local dy = (py + self.dy) / self.scale - self.cy;
local radian = atan2(dy, dx);
local r = sqrt(dx*dx + dy*dy);
if r >= rMax then
r = rMax;
elseif r <= rMin then
r = rMin;
end
self:UpdatePosition(radian, r);
end)
self.Shaft:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Widgets\\LightSetup\\ShadowShaft", nil, nil, "TRILINEAR");
self.DashedLine:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Widgets\\LightSetup\\ShadowDashedLine", nil, nil, "TRILINEAR");
self.DashedLine:SetWidth(2 * rMax);
local texOffset = ( 512 - 2 * rMax )/2/512
self.DashedLine:SetTexCoord(texOffset, 1 - texOffset, 0, 1);
--Initialization
self:UpdatePosition(defaultRadian, defaultRadius, true);
end
function NarciShadowRotationMixin:OnEnter()
end
function NarciShadowRotationMixin:OnLeave()
end
function NarciShadowRotationMixin:OnMouseDown()
local tx, ty = self:GetCenter(); --Thumb center
local cx, cy = self:GetParent():GetCenter(); --parent center
local px, py = GetCursorPosition();
local scale = self:GetEffectiveScale();
self.dx, self.dy = tx * scale - px, ty * scale - py;
self.cx, self.cy = cx, cy;
self.scale = scale;
self.UpdateFrame:Show();
self:LockHighlight();
LightControl.targetModelIndex = ACTIVE_MODEL_INDEX;
end
function NarciShadowRotationMixin:OnMouseUp()
self.UpdateFrame:Hide();
self:UnlockHighlight();
end
----------------------------------------------------
NarciActorPanelPopUpMixin = {};
function NarciActorPanelPopUpMixin:OnShow()
self:RegisterEvent("PLAYER_TARGET_CHANGED");
self:RegisterEvent("MODIFIER_STATE_CHANGED");
if UnitExists("target") then
self.AddTarget.isTypeLocked = not UnitIsPlayer("target");
end
self:OnModifierChanged();
end
function NarciActorPanelPopUpMixin:OnHide()
self:UnregisterEvent("PLAYER_TARGET_CHANGED");
self:UnregisterEvent("MODIFIER_STATE_CHANGED");
self:Hide();
self:SetAlpha(0);
end
function NarciActorPanelPopUpMixin:OnLeave()
if not self:IsMouseOver() then
FadeFrame(self, 0.15, 0);
end
end
function NarciActorPanelPopUpMixin:OnEvent(event, ...)
if event == "PLAYER_TARGET_CHANGED" then --fire when target's changed
local TargetText = self.AddTarget.Text;
if UnitExists("target") then
local name = UnitName("target");
local _, className = UnitClass("target");
local r, g, b = GetClassColor(className);
TargetText:SetTextColor(r, g, b);
SmartSetActorName(TargetText, name);
local isTargetNPC = not UnitIsPlayer("target");
self.AddTarget.isTypeLocked = isTargetNPC;
if self.AddTarget:IsMouseOver() then
self:UpdateWidgetTpe(isTargetNPC);
end
else
TargetText:SetTextColor(1, 0.3137, 0.3137); --Pastel Red
TargetText:SetText(ERR_GENERIC_NO_TARGET);
self.AddTarget.isTypeLocked = nil;
end
elseif event == "MODIFIER_STATE_CHANGED" then
local key, down = ...;
self:OnModifierChanged();
end
end
function NarciActorPanelPopUpMixin:OnModifierChanged()
if IsAltKeyDown() then
self:SetWidgetType(2);
self.Header.HotkeyAlt:SetHighlight(true);
else
self:SetWidgetType(1)
self.Header.HotkeyAlt:SetHighlight(false);
end
end
function NarciActorPanelPopUpMixin:SetWidgetType(index)
if self.isTypeLocked then
self.Header.WidgetType:SetText("CinematicModel");
else
if index == 1 then
self.Header.WidgetType:SetText("DressUpModel");
else
self.Header.WidgetType:SetText("CinematicModel");
end
end
self:UpdateLockVisual();
end
function NarciActorPanelPopUpMixin:UpdateWidgetTpe(lockType)
self.isTypeLocked = lockType;
if lockType then
self.Header.WidgetType:SetText("CinematicModel");
else
if IsAltKeyDown() then
self.Header.WidgetType:SetText("CinematicModel");
else
self.Header.WidgetType:SetText("DressUpModel");
end
end
self:UpdateLockVisual();
end
function NarciActorPanelPopUpMixin:UpdateLockVisual()
local state = self.isTypeLocked;
self.Header.LockIcon:SetShown(state);
self.Header.LeftText:SetShown(not state);
if state then
self.Header.WidgetType:SetTextColor(0.4, 0.4, 0.4);
else
self.Header.WidgetType:SetTextColor(0.65, 0.65, 0.65);
end
end
----------------------------------------------------
NarciModelIndexButtonMixin = {};
function NarciModelIndexButtonMixin:OnDoubleClick()
return;
end
function NarciModelIndexButtonMixin:OnEnter()
self.Highlight:Show();
if self:GetParent().UpdateFrame:IsShown() then return; end;
if self.hasModel then
if self.isModelHidden then
self.Status:SetText(L["Hidden"]);
else
self.Status:SetText(nil);
end
ShowIndexButtonLabel(self, true);
else
if not IsMouseButtonDown() then
local PopUp = self:GetParent().PopUp;
local TargetText = PopUp.AddTarget.Text;
if UnitExists("target") then
local name = UnitName("target");
local _, className = UnitClass("target");
local r, g, b = GetClassColor(className);
TargetText:SetTextColor(r, g, b);
SmartSetActorName(TargetText, name);
else
TargetText:SetTextColor(1, 0.3137, 0.3137); --Pastel Red
TargetText:SetText(ERR_GENERIC_NO_TARGET);
end
PopUp.parent = self;
PopUp.Index = self:GetID();
PopUp:SetPoint("CENTER", self, "CENTER", 0, 16);
FadeFrame(PopUp, 0.15, 1);
end
end
end
function NarciModelIndexButtonMixin:OnLeave()
if not (self.isOn or self.lockHighlight) then
self.Highlight:Hide();
end
if not self:GetParent().UpdateFrame:IsShown() then
self.Label:Hide();
self.LabelColor:Hide();
self.Status:Hide();
end
WidgetTooltip:HideTooltip();
local PopUp = self:GetParent().PopUp;
if not PopUp:IsMouseOver() then
FadeFrame(PopUp, 0.15, 0);
end
end
function NarciModelIndexButtonMixin:OnMouseDown()
self.ID:SetPoint("CENTER", 0.5, -0.5);
self.Icon:SetPoint("CENTER", 0.5, -0.5);
end
function NarciModelIndexButtonMixin:OnMouseUp()
self.ID:SetPoint("CENTER", 0, 0);
self.Icon:SetPoint("CENTER", 0, 0);
end
function NarciModelIndexButtonMixin:OnDragStart()
if not self.hasModel then return; end;
self:GetFrameLevel(60);
self:GetParent().ArtFrame.Label:SetText(L["Move To Font"]);
self.lockHighlight = true;
local UpdateFrame = self:GetParent().UpdateFrame;
UpdateFrame.ActiveButton = self:GetID();
UpdateFrame:Show();
ModelIndexButton_ShowSelfLabelAndHideOthers(self);
end
function NarciModelIndexButtonMixin:OnDragStop()
self:SetFrameLevel(21);
self:GetParent().ArtFrame.Label:SetText(L["Actor Index"]);
self:GetParent().UpdateFrame:Hide();
self.ID:SetPoint("CENTER", 0, 0);
self.Icon:SetPoint("CENTER", 0, 0);
if not self.hasModel then return; end;
local _, _, _, offset = self:GetPoint();
offset = tonumber(offset) - 12;
local AnimFrame = self.AnimFrame;
AnimFrame.StartX = offset;
AnimFrame.duration = math.max(0.05, math.abs(offset - AnimFrame.EndX) / 65);
--print("Anim Duration(s) = "..AnimFrame.duration)
self.lockHighlight = false;
if not self.isOn then
self.Highlight:Hide();
end
if not self:IsMouseOver() then
ShowIndexButtonLabel(self, false);
end
end
function NarciModelIndexButtonMixin:SetModelType(modelType)
local texOffset = 0;
if modelType == "player" then
texOffset = 0;
elseif modelType == "npc" then
texOffset = 1;
elseif modelType == "pet" then
texOffset = 3;
elseif modelType == "empty" then
texOffset = 7;
else
if modelType == "hidden" then
texOffset = 6;
elseif modelType == "virtual" then
texOffset = 2;
end
self.Border:SetTexCoord(0.125 * texOffset, 0.125 + 0.125 * texOffset, 0, 0.5);
self.Selection:SetTexCoord(0.125 * texOffset, 0.125 + 0.125 * texOffset, 0.5, 1);
return
end
self.texOffset = texOffset;
self:UpdateBorderTexture();
end
function NarciModelIndexButtonMixin:UpdateBorderTexture()
self.Border:SetTexCoord(0.125 * self.texOffset, 0.125 + 0.125 * self.texOffset, 0, 0.5);
self.Selection:SetTexCoord(0.125 * self.texOffset, 0.125 + 0.125 * self.texOffset, 0.5, 1);
end
function NarciModelIndexButtonMixin:SetSelection(state)
if state then
self.Highlight:Show();
self.Selection:Show();
self.isOn = true;
self.ID:SetShadowColor(1, 1, 1);
self.ID:SetTextColor(0, 0, 0);
else
self.Highlight:Hide();
self.Selection:Hide();
self.isOn = false;
self.ID:SetShadowColor(0, 0, 0);
self.ID:SetTextColor(0.25, 0.78, 0.92);
end
end
----------------------------------------------------
NarciModelSettingsMixin = {};
function NarciModelSettingsMixin:OnLoad()
SettingFrame = self;
BasicPanel = self.BasicPanel;
self:RegisterForDrag("LeftButton");
NarciAPI_CreateFadingFrame(self);
BasicPanel.CompactModeButton:SetScript("OnHide", CompactModeButton_OnHide);
end
function NarciModelSettingsMixin:OnEnter()
if IsMouseButtonDown() then return end;
HideGroundShadowControl();
NarciScreenshotToolbar:FadeOut(true);
self:FadeIn(0.15);
end
local function IsFrameFocused(frame)
return frame and frame:IsFocused();
end
function NarciModelSettingsMixin:OnLeave()
if self:IsMouseOver(24, -24, -36, 24) or Narci_SpellVisualBrowser:IsMouseOver(0, 0, 0, 0) or IsFrameFocused(self.TextOverlayMenu) or
IsFrameFocused(self.NPCBrowser) or IsFrameFocused(self.PetStable) or IsFrameFocused(self.StickerToggle)
or IsMouseButtonDown() then return end;
self:FadeOut(0.2);
end
function NarciModelSettingsMixin:OnHide()
--self:SetAlpha(0);
self:FadeOut(0, 0);
ResetIndexButton();
ExitGroupPhoto();
RestorePlayerInfo(1);
self:ClearAllPoints();
self:SetPoint("CENTER", Narci_VirtualLineRightCenter, "CENTER", 0 , 0);
self:SetPoint("BOTTOM", UIParent, "BOTTOM", 0 , 4);
self:SetUserPlaced(false);
self:UnregisterEvent("MODIFIER_STATE_CHANGED");
self:SetPanelAlpha(1, false);
FullSceenChromaKey:Hide();
FullSceenChromaKey:SetAlpha(0);
Narci_BackgroundDarkness:Hide();
Narci_BackgroundDarkness:SetAlpha(0);
NarciTextOverlayContainer:HideAllWidgets();
Narci_ColorPicker:Hide();
WeaponUpdator:SetListener(false);
NarciPhotoModeOutfitSelect:AddPlayerActor("player", PrimaryPlayerModel);
NarciPhotoModeOutfitSelect:SelectPreviewModel(1);
OutfitToggle:EnableButton();
PrimaryPlayerModel.customTransmogList = nil;
end
function NarciModelSettingsMixin:OnDragStart()
self:StartMoving();
end
function NarciModelSettingsMixin:OnDragStop()
self:StopMovingOrSizing();
end
function NarciModelSettingsMixin:SetPanelAlpha(value, smoothing)
local SpellVisualBrowser = self.SpellPanel;
local fromAlpha = self.BasicPanel:GetAlpha();
local UIFrameFadeIn = FadeFrame;
if smoothing then
local fadeDuation;
if value == 1 then
fadeDuation = 0.2;
else
fadeDuation = 0.5;
end
if SpellVisualBrowser.isActive then
UIFrameFadeIn(SpellVisualBrowser, fadeDuation, fromAlpha, value);
end
UIFrameFadeIn(self.ActorPanel, fadeDuation, fromAlpha, value);
UIFrameFadeIn(self.BasicPanel, fadeDuation, fromAlpha, value);
else
if SpellVisualBrowser.isActive then
SpellVisualBrowser:SetAlpha(value);
end
self.ActorPanel:SetAlpha(value);
self.BasicPanel:SetAlpha(value);
end
end
function NarciModelSettingsMixin:AddSubFrame(frame, key)
frame:SetParent(self.ActorPanel.NameFrame.HiddenFrames);
frame:Show();
if key and not self[key] then
self[key] = frame;
end
end
NarciOutfitToggleMixin = {};
function NarciOutfitToggleMixin:OnLoad()
OutfitToggle = self;
self.Label:SetText(L["Outfit"]);
NarciPhotoModeBar_OnLoad(self);
end
function NarciOutfitToggleMixin:OnClick()
NarciPhotoModeOutfitSelect:ToggleUI();
end
function NarciOutfitToggleMixin:OnEnter()
FadeFrame(self.Highlight, 0.2, 1);
end
function NarciOutfitToggleMixin:OnLeave()
FadeFrame(self.Highlight, 0.2, 0);
end
function NarciOutfitToggleMixin:DisableButton()
self:Disable();
self.Label:SetTextColor(0.42, 0.42, 0.42);
self.Arrow:SetVertexColor(0.5, 0.5, 0.5);
--self:SetAlpha(0.5);
end
function NarciOutfitToggleMixin:EnableButton()
self:Enable();
self.Label:SetTextColor(0.25, 0.78, 0.92);
self.Arrow:SetVertexColor(1, 1, 1);
--self:SetAlpha(1);
end
----------------------------------------------------
local ScreenshotListener = CreateFrame("Frame");
ScreenshotListener:RegisterEvent("SCREENSHOT_STARTED")
ScreenshotListener:RegisterEvent("SCREENSHOT_SUCCEEDED")
ScreenshotListener:RegisterEvent("PLAYER_ENTERING_WORLD");
ScreenshotListener:SetScript("OnEvent",function(self,event,...)
if event == "SCREENSHOT_STARTED" then
Temps.Alpha2 = SettingFrame:GetAlpha();
NarciScreenshotToolbar:FadeOut(true);
SettingFrame:SetAlpha(0);
elseif event == "SCREENSHOT_SUCCEEDED" then
SettingFrame:SetAlpha(Temps.Alpha2);
if NUM_UNCAPTURED_LAYERS >= 0 then
After(1.5, function()
StartAutoCapture_SkipItems();
end)
end
NarciAPI.UpdateScreenshotsCounter();
elseif event == "PLAYER_ENTERING_WORLD" then
self:UnregisterEvent(event);
ActorPanel = Narci_ActorPanel;
ModelIndexButton_ResetReposition();
InitializePlayerInfo(1);
UpdateActorName(1);
--CreateRaceButtonList(Narci_RaceOptionFrame, "Narci_RaceOptionButton_Template", RaceList, 6); --"SetCustomRace" removed in 10.1.5
After(1, function()
CacheModel();
end)
NarciModelControl_AnimationSlider.onValueChangedFunc = function(value)
local id = AnimationIDEditBox:GetNumber();
local model = ModelFrames[ACTIVE_MODEL_INDEX];
model:Freeze(id, model.variationID or 0, value);
end
end
end)
----------------------------------------------------
function Narci:EquipmentItemByItemID(modelIndex, itemID, itemModID)
local appearanceID, sourceID = C_TransmogCollection.GetItemInfo(itemID, itemModID);
local name = C_Item.GetItemInfo(itemID) or "";
After(0.1, function()
name = C_Item.GetItemInfo(itemID) or "";
print(name.." | ".."AppearanceID: "..appearanceID.." ".." SourceID"..sourceID);
end)
local model = ModelFrames[modelIndex];
if model then
model:TryOn(sourceID);
else
print("Can't find model #"..modelIndex);
end
end
function Narci:GetActiveActor()
return ModelFrames[ACTIVE_MODEL_INDEX]
end
function Narci:LoadOutfitSlashCommand(msg)
msg = string.gsub(msg, "/outfit%s+", "");
local itemTransmogInfoList = TransmogUtil.ParseOutfitSlashCommand(msg);
local model = ModelFrames[ACTIVE_MODEL_INDEX];
if itemTransmogInfoList then
model:Undress();
for slotID, info in ipairs(itemTransmogInfoList) do
model:SetItemTransmogInfo(info, slotID);
end
end
end
function NarciPhotoModeAPI:SetMaxAnimationID(value)
if value > maxAnimationID then
maxAnimationID = value;
end
end
NarciPhotoModeModelContainerMixin = {};
function NarciPhotoModeModelContainerMixin:OnLoad()
ModelContainer = self;
end
function NarciPhotoModeModelContainerMixin:OnShow()
end
function NarciPhotoModeModelContainerMixin:OnHide()
end
function NarciPhotoModeModelContainerMixin:ClearOtherActors()
--excepet the player
HideAllModels();
end
function NarciPhotoModeModelContainerMixin:HideAndClearModel()
self:Hide();
HideAllModels();
end
NarciPhotoModeLightDirectionControllerMixin = {
thumb_OnMouseDown = function(self)
self:LockHighlight();
local UpdateFrame = self:GetParent().UpdateFrame;
local mx, my = self:GetCenter();
local px, py = GetCursorPosition();
local scale = self:GetEffectiveScale();
UpdateFrame.dx, UpdateFrame.dy = mx * scale - px, my * scale - py;
UpdateFrame.mx, UpdateFrame.my = self:GetParent():GetCenter();
UpdateFrame:Show();
end,
thumb_OnMouseUp = function(self)
self:UnlockHighlight();
self:GetParent().UpdateFrame:Hide();
end,
updateFrame_OnShow = function(self)
self.scale = self:GetParent():GetEffectiveScale() or 1;
end
};
local function LightButtonUpdateFrame_OnUpdate(self, elapsed)
self.t = self.t + elapsed;
if self.t < 0.016 then return end;
local radian;
local px, py = GetCursorPosition();
--Adjust for mousedown start offset
px, py = (px + self.dx) / self.scale, (py + self.dy) / self.scale;
radian = atan2(py - self.my, px - self.mx);
if self.limit then
if radian >= pi/2 then
radian = pi/2 - 0.001;
elseif radian <= -pi/2 then
radian = -pi/2 + 0.001;
end
LightControl.angleZ = radian;
else
LightControl.angleXY = radian;
local FaceLeft = self:GetParent():GetParent().SideView.FaceLeft;
local FaceRight = self:GetParent():GetParent().SideView.FaceRight;
if FaceLeft and FaceRight then
local degree2 = math.deg(radian);
if degree2 > 0 then
FaceLeft:SetAlpha(1);
FaceRight:SetAlpha(0);
elseif degree2 <= 0 and degree2 >= -180 then
FaceLeft:SetAlpha(0);
FaceRight:SetAlpha(1);
end
end
end
--Not sure why MaskTexture can only get rotated after mouse-up event.
self:GetParent().LightColor:SetRotation(radian);
local r = self.r;
local x, y = r*cos(radian), r*sin(radian);
self.Thumb:SetPoint("CENTER", x, y);
self.Thumb.Tex:SetRotation(radian);
self.Thumb.Highlight:SetRotation(radian);
LightControl:UpdateModel();
end
local function LightButtonUpdateFrame_OnLoad(self)
local r = self:GetParent():GetWidth()/2 - 4;
self.r = r;
self.t = 0;
LightControl.radius = r;
local button = self:GetParent().Thumb;
local radian = self.radian;
local x, y = self.r*math.cos(radian), self.r*math.sin(radian);
button:SetPoint("CENTER", x, y);
button.Tex:SetRotation(radian);
button.Highlight:SetRotation(radian);
self:GetParent().LightColor:SetRotation(radian);
if self.limit then
LightControl.parentButton1 = button;
--LightControl.BeamMask1 = self:GetParent().BeamMask;
else
LightControl.parentButton2 = button;
--LightControl.BeamMask2 = self:GetParent().BeamMask;
end
self:SetScript("OnUpdate", LightButtonUpdateFrame_OnUpdate);
end
function NarciPhotoModeLightDirectionControllerMixin:OnLoad()
if self.view == "side" then
self.Background:SetTexCoord(0.375, 0.75, 0, 0.75);
self.UpdateFrame.dx, self.UpdateFrame.dy = 0, 0;
self.UpdateFrame.radian = math.pi/4;
self.UpdateFrame.limit = true;
elseif self.view == "top" then
self.Background:SetTexCoord(0, 0.375, 0, 0.75);
self.UpdateFrame.dx, self.UpdateFrame.dy = 0, 0;
self.UpdateFrame.radian = -3*math.pi/4;
end
self.Thumb:SetScript("OnMouseDown", self.thumb_OnMouseDown);
self.Thumb:SetScript("OnMouseUp", self.thumb_OnMouseUp);
LightButtonUpdateFrame_OnLoad(self.UpdateFrame);
self.UpdateFrame:SetScript("OnShow", self.updateFrame_OnShow);
self.UpdateFrame.Thumb = self.Thumb;
end
NarciPhotoModeCaptureButtonMixin = {};
function NarciPhotoModeCaptureButtonMixin:OnLoad()
CaptureButton = self;
self.numCaptures = 4;
self.tooltipHeader = L["Save Layers"];
self.tooltipDescription = L["Save Layers Tooltip"];
self.tooltipImage = "SaveLayers";
end
function NarciPhotoModeCaptureButtonMixin:OnClick()
self:Disable()
PauseAllModel(true);
WidgetTooltip:Hide();
Narci_Character:Hide();
Narci_VignetteLeft:SetAlpha(0);
Narci_VignetteRightSmall:SetAlpha(0);
NUM_UNCAPTURED_LAYERS = self.numCaptures;
Screenshot();
end
function NarciPhotoModeCaptureButtonMixin:OnEnter()
if NUM_UNCAPTURED_LAYERS == -1 then
self.Value:SetText(self.numCaptures);
WidgetTooltip:ShowButtonTooltip(self);
end
end
function NarciPhotoModeCaptureButtonMixin:OnLeave()
if NUM_UNCAPTURED_LAYERS == -1 then
self.Value:SetText(0);
WidgetTooltip:HideTooltip();
end
end
function NarciPhotoModeCaptureButtonMixin:OnHide()
self:Enable();
end
local function ShrinkModelHitRect(offsetX)
HIT_RECT_OFFSET = offsetX;
local W0 = WorldFrame:GetWidth();
local newWidth = 2/3*W0 + offsetX;
local _G = _G;
local model;
for i = 1, NUM_MAX_ACTORS do
model = _G["NarciPlayerModelFrame"..i];
if model then
model:SetHitRectInsets(newWidth, 0, 0, 32.0);
end
model = _G["NarciNPCModelFrame"..i];
if model then
model:SetHitRectInsets(newWidth, 0, 0, 32.0);
end
end
local indicator = Narci_ModelInteractiveArea;
indicator:SetWidth(W0 - newWidth);
if ModelContainer:IsShown() then
indicator.InOut:Stop();
indicator.InOut:Play();
indicator:Show();
else
indicator:Hide();
end
end
do
local _, addon = ...
local SettingFunctions = addon.SettingFunctions;
function SettingFunctions.SetModelPanelScale(scale, db)
if scale == nil then
scale = db["ModelPanelScale"] or 1;
end
SettingFrame:SetScale(scale);
end
function SettingFunctions.SetModelHitRectShrinkage(shrinkX, db)
if shrinkX == nil then
shrinkX = db["ShrinkArea"] or 0;
end
ShrinkModelHitRect(shrinkX);
end
function SettingFunctions.SetModelLoopAnimation(loop, db)
if loop == nil then
loop = db["LoopAnimation"] or false;
end
LOOP_ANIMATION = loop;
end
end
--[[
function PrintIcon(id)
print("|T"..id..":18:18:0:0:64:64:4:60:4:60|t")
end
**Peter Odox**
| Slot | Name | Source |
|:--|:--|:--|
| Head | [Netherstorm Eyepatch](https://www.wowhead.com/item=29979) | Quest |
| Shoulder | [Lightdrinker Shoulders](https://www.wowhead.com/item=119702) | |
| Back | [Loa Exultant's Shroud](https://www.wowhead.com/item=165512) | Conclave of the Chosen Battle of Dazar'alor Mythic |
| Chest | [Vest of the Dashing Scoundrel](https://www.wowhead.com/item=152160) | Eonar the Life-Binder Antorus, the Burning Throne Raid Finder |
| Shirt | [Blue Lumberjack Shirt](https://www.wowhead.com/item=41249) | Profession |
| Wrist | [Codemaster's Cuffs](https://www.wowhead.com/item=63660) | Quest |
| Hands | [Honorable Combatant's Leather Gauntlets](https://www.wowhead.com/item=161949) | Profession |
| Waist | [Hound-Jowl Waistband](https://www.wowhead.com/item=159341) | Soulbound Goliath Waycrest Manor Heroic |
| Legs | [Pants of the Dashing Scoundrel](https://www.wowhead.com/item=152164) | Imonar the Soulhunter Antorus, the Burning Throne Raid Finder |
| Feet | [Honorable Combatant's Leather Treads](https://www.wowhead.com/item=161948) | Profession |
| Main Hand | [Dreadblades](https://www.wowhead.com/item=128872) | Artifact |
| Off Hand | [Dreadblades](https://www.wowhead.com/item=134552) | Artifact |
https://www.wowhead.com/dressing-room#sazm0zJ89cRszNz9m8RZY8zVy8OP48zgJ8WqC8zLJ8PdT8zmw87oSxB8zT48SIf8zLA8Pdx8zmw8Sxl8zT48CiZ808CiY87cf
https://www.wowhead.com/dressing-room#sm0m0zJ89mVm0V9m8RZY8zVy8OP48zgJ8WqC8zLO8PdT8zmi87oURd8zT48SIf808Pdx8zmi8URb8zT48CiZ808CiY87cw
Model FileID
Calia Menethil 2997555
Jaina Proudmoore No Weapon 1717164
Derek Proudmoore 2831231
Dogs
320622
Patch SpellVisualKit max ID
8.2.0 119100
8.2.5 120270
/run PrimaryPlayerModel:SetLight(true, false, -pi/4, pi/4, 0, 1, 1, 1, 1, 500, 10, 10, 10);
function SetModelID(fileID)
local m = NarciNPCModelFrame2;
local a, b, c = m:GetPosition();
local x, y, z = m:GetCameraPosition();
m:SetModel(fileID);
After(1, function()
m:MakeCurrentCameraCustom();
m:SetPosition(a, b, c);
m:SetCameraPosition(x, y, z);
m:SetCameraTarget(0, 0, 0.8);
end);
end
/script local m=Narci.ActiveModel;local v=m.variationID;v=(v<15 and v+1)or(0);m.variationID=v;m:PlayAnimation(m.animationID);print(v);
/script local f=function(s) s:SetAnimation(s.animationID or 0,s.variationID or 0) end;local m;for i=1,8 do m=_G["NarciPlayerModelFrame"..i] if m then m:SetScript("OnAnimFinished", f) end end
/script local f=function(s) if s then s:SetScript("OnAnimFinished",function() s:SetAnimation(s.animationID or 0,s.variationID or 0) end) end end;for i=1,8 do f(_G["NarciPlayerModelFrame"..i]) f(_G["NarciNPCModelFrame"..i]) end
--]]
local Spinner;
function Narci.SpinCurrentActor()
local actor = Narci:GetActiveActor();
if actor then
if not Spinner then
Spinner = CreateFrame("Frame");
Spinner:SetScript("OnHide", function(f)
f:Hide();
end);
end
end
Spinner.t = 0;
Spinner.yaw = actor:GetFacing();
Spinner:Show();
Spinner:SetParent(actor);
local pi2 = math.pi*2;
local t = 6;
local dA = pi2/t;
Spinner:SetScript("OnUpdate", function(f, elapsed)
f.yaw = f.yaw + elapsed*dA;
if f.yaw > pi2 then
f.yaw = f.yaw - pi2;
end
actor:SetFacing(f.yaw);
end);
end
function Narci.ApplyNeutralLight()
--Same as WardrobeItemsModelMixin
local actor = Narci:GetActiveActor();
if actor then
local lightValues = { omnidirectional = false, point = CreateVector3D(-1, 1, -1), ambientIntensity = 1.05, ambientColor = CreateColor(1, 1, 1), diffuseIntensity = 0, diffuseColor = CreateColor(1, 1, 1) };
local enabled = true;
actor:SetLight(enabled, lightValues);
end
end
local WardrobeModelContainer;
function Narci.ToggleWardrobeItemModel()
if not WardrobeModelContainer then
local scale = 2;
WardrobeModelContainer = CreateFrame("DressUpModel", nil, UIParent);
WardrobeModelContainer:SetSize(78*scale, 104*scale);
WardrobeModelContainer:SetPoint("CENTER", UIParent, "CENTER", 0, 0);
WardrobeModelContainer:SetIgnoreParentScale(true);
WardrobeModelContainer:SetIgnoreParentAlpha(true);
local bg = WardrobeModelContainer:CreateTexture(nil, "BACKGROUND");
bg:SetAllPoints(true);
bg:SetColorTexture(0, 0, 0);
WardrobeModelContainer:SetScript("OnHide", function(self)
self:Hide();
end);
WardrobeModelContainer:SetScript("OnShow", function(self)
local visualID = 29124; --Hide Helm --/dump GetMouseFocus().visualInfo
local cameraVariation = nil;
local cameraID = C_TransmogCollection.GetAppearanceCameraID(visualID, cameraVariation);
self.cameraID = cameraID;
self:SetUnit("player", false, PlayerUtil.ShouldUseNativeFormInModelScene());
self:TryOn(78420); --Chest
end);
WardrobeModelContainer:SetScript("OnEnter", function()
end);
WardrobeModelContainer:SetScript("OnModelLoaded", function(self)
if self.cameraID then
Model_ApplyUICamera(self, self.cameraID);
end
end);
local lightValues = { omnidirectional = false, point = CreateVector3D(-1, 1, -1), ambientIntensity = 1.05, ambientColor = CreateColor(1, 1, 1), diffuseIntensity = 0, diffuseColor = CreateColor(1, 1, 1) };
local enabled = true;
WardrobeModelContainer:SetLight(enabled, lightValues);
WardrobeModelContainer:SetAutoDress(false);
WardrobeModelContainer:Hide();
end
WardrobeModelContainer:SetShown(not WardrobeModelContainer:IsShown());
end
local function SetChromaKeyColor(r, g, b, a)
local tex = Narci_ModelContainer.ChromaKey;
if not r then
tex:Hide();
return
end
a = a or 1;
if type(r) == "string" then
local color = NarciAPI.ConvertHexColorToRGB(r);
r, g, b = unpack(color);
a = g or 1;
else
r = (r or 0)/255;
g = (g or 0)/255;
b = (b or 0)/255;
end
tex:SetAlpha(1);
tex:SetColorTexture(r, g, b, 1);
tex:SetAlpha(a);
tex:Show();
end
NarciPhotoModeAPI.SetChromaKeyColor = SetChromaKeyColor;
--Play a sequence of animation on the actor
local function Moodel_OnAnimFinished_PlaySequence(self)
self.sequenceIndex = self.sequenceIndex + 1;
local nextAnimationID = self.animationSequence[self.sequenceIndex];
if nextAnimationID then
self:SetAnimation(nextAnimationID, 0);
else
self:SetScript("OnAnimFinished", NarciGenericModelMixin.OnAnimFinished);
self.animationSequence = nil;
self.sequenceIndex = nil;
end
end
local function PlayAnimationSequenceOnModel(moldeIndex, ...)
-- ... animationIDs
local model = ModelFrames[moldeIndex];
if model and model:IsVisible() then
model.animationSequence = {...};
model.sequenceIndex = 1;
model:SetScript("OnAnimFinished", Moodel_OnAnimFinished_PlaySequence);
model:SetAnimation(model.animationSequence[1], 0);
end
end
Narci.PlayAnimationSequenceOnModel = PlayAnimationSequenceOnModel;