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.
2282 lines
70 KiB
2282 lines
70 KiB
|
5 years ago
|
local upper = string.upper;
|
||
|
|
local gsub = string.gsub;
|
||
|
|
local After = C_Timer.After;
|
||
|
|
|
||
|
|
local CreateAnimationFrame = NarciAPI_CreateAnimationFrame;
|
||
|
|
local FadeFrame = NarciAPI_FadeFrame;
|
||
|
|
local UIFrameFadeIn = UIFrameFadeIn;
|
||
|
|
|
||
|
|
local max = math.max;
|
||
|
|
local min = math.min;
|
||
|
|
local cos = math.cos;
|
||
|
|
local sin = math.sin;
|
||
|
|
local sqrt = math.sqrt;
|
||
|
|
local floor = math.floor;
|
||
|
|
local pow = math.pow;
|
||
|
|
local abs = math.abs;
|
||
|
|
local pi = math.pi;
|
||
|
|
local Clamp = Clamp;
|
||
|
|
|
||
|
|
local function RotateByYaw(x, y, z, x0, y0, z0, yaw)
|
||
|
|
local px, py, pz = x - x0, y - y0, z - z0;
|
||
|
|
local sinYaw = sin(yaw);
|
||
|
|
local cosYaw = cos(yaw);
|
||
|
|
return x0 + px * cosYaw - py * sinYaw, y0 + px * sinYaw + py * cosYaw, z
|
||
|
|
end
|
||
|
|
|
||
|
|
local function linear(t, b, e, d)
|
||
|
|
return (e - b) * t / d + b
|
||
|
|
end
|
||
|
|
|
||
|
|
local function outSine(t, b, e, d)
|
||
|
|
return (e - b) * sin(t / d * (pi / 2)) + b
|
||
|
|
end
|
||
|
|
|
||
|
|
local function inOutSine(t, b, e, d)
|
||
|
|
return (b - e) / 2 * (cos(pi * t / d) - 1) + b
|
||
|
|
end
|
||
|
|
|
||
|
|
local function inOutSineZero(t, b, e, d)
|
||
|
|
if d == 0 then
|
||
|
|
return e
|
||
|
|
else
|
||
|
|
return (b - e) / 2 * (cos(pi * t / d) - 1) + b
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
local function GetSetConciseName(name)
|
||
|
|
if not name then return end
|
||
|
|
name = gsub(name, "\'s.+", "");
|
||
|
|
name = gsub(name, ".+of%s", "");
|
||
|
|
name = upper(name);
|
||
|
|
return name
|
||
|
|
end
|
||
|
|
|
||
|
|
local GRAY_90 = 0.08;
|
||
|
|
local GRAY_20 = 0.8;
|
||
|
|
local GRAY_50 = 0.46;
|
||
|
|
local GRAY_30 = 0.66;
|
||
|
|
|
||
|
|
local GetSourceInfo = C_TransmogCollection.GetSourceInfo;
|
||
|
|
local GetSlotForInventoryType = C_Transmog.GetSlotForInventoryType; --sourceInfo.invType
|
||
|
|
|
||
|
|
--C_TransmogSets
|
||
|
|
local GetBaseSets = C_TransmogSets.GetBaseSets;
|
||
|
|
local GetSetInfo = C_TransmogSets.GetSetInfo;
|
||
|
|
local GetVariantSets = C_TransmogSets.GetVariantSets;
|
||
|
|
local GetSetSources = C_TransmogSets.GetSetSources;
|
||
|
|
|
||
|
|
local NarciModelInfo = NarciModelInfo;
|
||
|
|
local YAW_FACING_FORWARD, PLAYER_SCALE, OFFSET_AMPLIFIER ,PANNING_OFFSETS_FULL_CENTRAL, PANNING_OFFSETS_FULL_RIGHT, PANNING_OFFSETS_UPPER, PANNING_OFFSETS_LOWER = NarciModelInfo:GetSceneInfo(); --Facing, Scale
|
||
|
|
local OFFSET_YAW_STEP = -15/360 * pi;
|
||
|
|
|
||
|
|
local ACTOR_POSITIONS = {
|
||
|
|
--[numActor] = { [1] = {offsetY-s}, [2] = {offsetYaw-s} }
|
||
|
|
[1] = {{0}, {YAW_FACING_FORWARD}},
|
||
|
|
[2] = {{OFFSET_AMPLIFIER*0.45, -OFFSET_AMPLIFIER*0.45}, {YAW_FACING_FORWARD -OFFSET_YAW_STEP, YAW_FACING_FORWARD + OFFSET_YAW_STEP}},
|
||
|
|
[3] = {{OFFSET_AMPLIFIER*0.85, 0, -OFFSET_AMPLIFIER*0.85}, {YAW_FACING_FORWARD -OFFSET_YAW_STEP, YAW_FACING_FORWARD, YAW_FACING_FORWARD + OFFSET_YAW_STEP}},
|
||
|
|
[4] = {{OFFSET_AMPLIFIER*1.35, OFFSET_AMPLIFIER*0.45, -OFFSET_AMPLIFIER*0.45, -OFFSET_AMPLIFIER*1.35}, {YAW_FACING_FORWARD -2*OFFSET_YAW_STEP, YAW_FACING_FORWARD -OFFSET_YAW_STEP, YAW_FACING_FORWARD + OFFSET_YAW_STEP, YAW_FACING_FORWARD + 2*OFFSET_YAW_STEP}},
|
||
|
|
};
|
||
|
|
|
||
|
|
local ACTOR_POSITIONS_INWARD = {
|
||
|
|
--offsetX
|
||
|
|
[1] = {0},
|
||
|
|
[2] = {0, 0},
|
||
|
|
[3] = {0.2, 0, 0.2},
|
||
|
|
[4] = {0.2, 0, 0, 0.2},
|
||
|
|
};
|
||
|
|
|
||
|
|
local SHADOW_OFFSET = 70;
|
||
|
|
local SHADOW_POSITIONS = {
|
||
|
|
[1] = {0},
|
||
|
|
[2] = {-SHADOW_OFFSET, SHADOW_OFFSET},
|
||
|
|
[3] = {-2*SHADOW_OFFSET, 0, 2*SHADOW_OFFSET},
|
||
|
|
[4] = {-3*SHADOW_OFFSET, -SHADOW_OFFSET, SHADOW_OFFSET, 3*SHADOW_OFFSET},
|
||
|
|
};
|
||
|
|
|
||
|
|
--Camera Info
|
||
|
|
local ZOOM_DISTANCE_CLOSE = 2.7;
|
||
|
|
local ZOOM_DISTANCE_FAR = 4.2;
|
||
|
|
local BLEND_DURATION = 1;
|
||
|
|
|
||
|
|
--Objects
|
||
|
|
local OutfitFrame;
|
||
|
|
local ModelScene, ModelSceneCamera;
|
||
|
|
local SetList, SetListScrollChild, SetListModel, BlackOverlay;
|
||
|
|
local LeftTab, ItemModelTab, ItemListTab;
|
||
|
|
|
||
|
|
------------------------------------------------------------------
|
||
|
|
--UI Animation
|
||
|
|
local VERTICAL_SCROLL = 202;
|
||
|
|
local animShowSetList = CreateAnimationFrame(0.25);
|
||
|
|
animShowSetList:SetScript("OnUpdate", function(self, elapsed)
|
||
|
|
self.total = self.total + elapsed;
|
||
|
|
local h = inOutSine(self.total, self.fromHeight, self.toHeight, self.duration);
|
||
|
|
if self.total >= self.duration then
|
||
|
|
h = self.toHeight;
|
||
|
|
self:Hide();
|
||
|
|
end
|
||
|
|
self.object:SetHeight(h);
|
||
|
|
self.frame:SetVerticalScroll(h - VERTICAL_SCROLL);
|
||
|
|
end)
|
||
|
|
|
||
|
|
local function ShowSetList(show)
|
||
|
|
if animShowSetList:IsShown() then return false end
|
||
|
|
|
||
|
|
if show then
|
||
|
|
animShowSetList.fromHeight = 87;
|
||
|
|
animShowSetList.toHeight = 87; --67
|
||
|
|
FadeFrame(BlackOverlay, 0.25, "IN");
|
||
|
|
FadeFrame(SetListScrollChild, 0.15, "Forced_IN");
|
||
|
|
FadeFrame(ModelScene.TextFrame, 0.15, "OUT");
|
||
|
|
FadeFrame(SetListModel, 0.15, "Forced_IN");
|
||
|
|
else
|
||
|
|
animShowSetList.fromHeight = 87;
|
||
|
|
animShowSetList.toHeight = 0.5;
|
||
|
|
FadeFrame(BlackOverlay, 0.25, "OUT");
|
||
|
|
FadeFrame(SetListScrollChild, 0.25, "OUT");
|
||
|
|
FadeFrame(ModelScene.TextFrame, 0.15, "IN");
|
||
|
|
FadeFrame(SetListModel, 0.15, "OUT");
|
||
|
|
end
|
||
|
|
|
||
|
|
animShowSetList:Show();
|
||
|
|
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
---------------------
|
||
|
|
local animLeftTabEntance = CreateAnimationFrame(0.25);
|
||
|
|
animLeftTabEntance:SetScript("OnUpdate", function(self, elapsed)
|
||
|
|
self.total = self.total + elapsed;
|
||
|
|
local offset = outSine(self.total, self.fromX, self.toX, self.duration);
|
||
|
|
if self.total >= self.duration then
|
||
|
|
offset = self.toX;
|
||
|
|
self:Hide();
|
||
|
|
end
|
||
|
|
self.object:SetPoint("TOPLEFT", LeftTab, "TOPLEFT", offset, -44);
|
||
|
|
end)
|
||
|
|
|
||
|
|
local function ShowLeftTab(show)
|
||
|
|
if show then
|
||
|
|
--animLeftTabEntance.toX = 20;
|
||
|
|
FadeFrame(LeftTab, 0.15, "IN");
|
||
|
|
SetList:Hide();
|
||
|
|
else
|
||
|
|
--animLeftTabEntance.toX = -300;
|
||
|
|
SetList:Show();
|
||
|
|
FadeFrame(LeftTab, 0.25, "OUT");
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local animNavigationHighlight = CreateAnimationFrame(0.25);
|
||
|
|
animNavigationHighlight:SetScript("OnUpdate", function(self, elapsed)
|
||
|
|
self.total = self.total + elapsed;
|
||
|
|
local offset = inOutSine(self.total, self.fromX, self.toX, self.duration);
|
||
|
|
if self.total >= self.duration then
|
||
|
|
offset = self.toX;
|
||
|
|
self:Hide();
|
||
|
|
end
|
||
|
|
self.object:SetPoint("CENTER", self.anchorTo, "LEFT", offset, 0);
|
||
|
|
end)
|
||
|
|
|
||
|
|
local function MoveHighlightTo(index)
|
||
|
|
animNavigationHighlight:Hide();
|
||
|
|
local _;
|
||
|
|
_, animNavigationHighlight.anchorTo, _, animNavigationHighlight.fromX = animNavigationHighlight.object:GetPoint();
|
||
|
|
animNavigationHighlight.toX = (index - 1) * 60 + 30.5;
|
||
|
|
animNavigationHighlight:Show();
|
||
|
|
end
|
||
|
|
|
||
|
|
-----------------------
|
||
|
|
----Camera Movement----
|
||
|
|
-----------------------
|
||
|
|
local NarciCamera = {};
|
||
|
|
|
||
|
|
local ANIMATION_PRESETS = {
|
||
|
|
[0] = {0, 0, 0}, --Stand Pause
|
||
|
|
[1] = {0, 0, 0.5},
|
||
|
|
[2] = {11, 0, 1}, --Shuffle Left
|
||
|
|
[3] = {12, 0, 1}, --Shuffle Right
|
||
|
|
[4] = {67, 0, 1}, --Wave
|
||
|
|
};
|
||
|
|
|
||
|
|
local BOUNDING_BOX_DISTANCE = 0.35; --0.25
|
||
|
|
local STAGE_SIZE = {1.9, 1.6}; --2.7 +y, +z camera.panningYOffset ~ 43.15 --Height Varies BE/VE 1.6, Female Troll 1.75
|
||
|
|
local maxBoundingBoxHeight = STAGE_SIZE[2];
|
||
|
|
local maxBoundingBoxWidth = (STAGE_SIZE[1] * 2 - BOUNDING_BOX_DISTANCE * 3) / 4;
|
||
|
|
local modelXSize3D, modelYSize3D = -1, -1;
|
||
|
|
local modelXSize2D, modelYSize2D = -1, -1;
|
||
|
|
|
||
|
|
local function SetActorAnimation(actor, animationIndex)
|
||
|
|
--animationIndex ~ Preset
|
||
|
|
animationIndex = animationIndex or 0;
|
||
|
|
actor:SetAnimationData( unpack( ANIMATION_PRESETS[animationIndex] ) );
|
||
|
|
end
|
||
|
|
|
||
|
|
local animCameraMovement = CreateAnimationFrame(0.25);
|
||
|
|
animCameraMovement:SetScript("OnUpdate", function(self, elapsed)
|
||
|
|
self.total = self.total + elapsed;
|
||
|
|
local offsetX = inOutSine(self.total, self.fromX, self.toX, self.duration);
|
||
|
|
local offsetY = inOutSine(self.total, self.fromY, self.toY, self.duration);
|
||
|
|
local actorX = inOutSine(self.total, self.fromActorX, self.toActorX, self.duration);
|
||
|
|
local actorY = inOutSine(self.total, self.fromActorY, self.toActorY, self.duration);
|
||
|
|
local actorYaw = outSine(self.total, self.fromYaw, self.toYaw, self.duration);
|
||
|
|
|
||
|
|
if self.total >= self.duration then
|
||
|
|
offsetX = self.toX;
|
||
|
|
offsetY = self.toY;
|
||
|
|
actorYaw = self.toYaw;
|
||
|
|
actorX, actorY = self.toActorX, self.toActorY;
|
||
|
|
self:Hide();
|
||
|
|
end
|
||
|
|
ModelSceneCamera.panningXOffset = offsetX;
|
||
|
|
ModelSceneCamera.panningYOffset = offsetY;
|
||
|
|
self.actor:MoveTo(actorX, actorY, 0);
|
||
|
|
self.actor:SetFacing(actorYaw);
|
||
|
|
end)
|
||
|
|
|
||
|
|
local animActorMovement = CreateAnimationFrame(0.66);
|
||
|
|
animActorMovement:SetScript("OnUpdate", function(self, elapsed)
|
||
|
|
self.total = self.total + elapsed;
|
||
|
|
local actor2Y = inOutSine(self.total, 0.5, 0, self.duration);
|
||
|
|
local actor2X = inOutSine(self.total, self.fromActor2X, self.toActor2X, self.duration);
|
||
|
|
|
||
|
|
if self.total >= self.duration then
|
||
|
|
actor2X = self.toActor2X;
|
||
|
|
self:Hide();
|
||
|
|
end
|
||
|
|
|
||
|
|
--self.actor1:MoveTo(-actor2X, 0, 0);
|
||
|
|
self.actor2:MoveTo(actor2X, actor2Y, 0);
|
||
|
|
end)
|
||
|
|
|
||
|
|
local function Actor2EnterScene()
|
||
|
|
local animActorMovement = animActorMovement;
|
||
|
|
animActorMovement:Hide();
|
||
|
|
|
||
|
|
if OutfitFrame:GetActiveTabIndex() == 1 then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
if not animActorMovement.toActor2X then
|
||
|
|
animActorMovement.toActor2X = (modelXSize3D + BOUNDING_BOX_DISTANCE)/2;
|
||
|
|
end
|
||
|
|
|
||
|
|
local actor2 = animActorMovement.actor2;
|
||
|
|
actor2:SetFacing(YAW_FACING_FORWARD);
|
||
|
|
SetActorAnimation(actor2, 1);
|
||
|
|
|
||
|
|
animActorMovement.fromActor2X = ModelScene.activeActor:GetPosition();
|
||
|
|
animActorMovement:Show();
|
||
|
|
NarciCamera.isSecondActorVisible = true;
|
||
|
|
|
||
|
|
FadeFrame(actor2, 0.25, "IN");
|
||
|
|
actor2.groundShadow:Show();
|
||
|
|
--local smoothing = true;
|
||
|
|
--ModelScene:ShowGroundShadow(2, smoothing);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
NarciCamera.executionFrame = animCameraMovement;
|
||
|
|
|
||
|
|
NarciCamera.CAMERA_PRESETS = {
|
||
|
|
--[i] = {closeUp, down, back, central, hideBackdrop}
|
||
|
|
[1] = {true, false, false, false}, --Bust Front
|
||
|
|
[2] = {true, true, false, false}, --Lower Body
|
||
|
|
[3] = {false, false, false, false}, --Full Body Front
|
||
|
|
[4] = {false, false, true, false}, --Full Body Back
|
||
|
|
|
||
|
|
[5] = {false, false, false, true, true}, --Full Body Front Central --Slot fully collected
|
||
|
|
[6] = {false, false, false, true, true}, --Full Body Front Central --Slot missing
|
||
|
|
};
|
||
|
|
|
||
|
|
function NarciCamera:IsSameCamera(newIndex)
|
||
|
|
if newIndex == self.lastIndex then
|
||
|
|
return true
|
||
|
|
else
|
||
|
|
self.lastIndex = newIndex;
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciCamera:GoToCamera(index, transitionDuration)
|
||
|
|
local closeUp, down, back, central, hideBackdop = unpack( self.CAMERA_PRESETS[index] );
|
||
|
|
|
||
|
|
if self:IsSameCamera(index) then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
local frame = self.executionFrame;
|
||
|
|
frame:Hide();
|
||
|
|
|
||
|
|
local ModelScene = ModelScene;
|
||
|
|
local ModelSceneCamera = ModelSceneCamera;
|
||
|
|
|
||
|
|
local duration;
|
||
|
|
local past = frame.total;
|
||
|
|
|
||
|
|
if past == 0 then
|
||
|
|
duration = transitionDuration or BLEND_DURATION;
|
||
|
|
else
|
||
|
|
duration = Clamp(past, 0.66, BLEND_DURATION);
|
||
|
|
end
|
||
|
|
|
||
|
|
local actor = frame.actor;
|
||
|
|
local toActorX, toActorY;
|
||
|
|
local finalZoom, finalYaw;
|
||
|
|
local panningOffsets;
|
||
|
|
|
||
|
|
if hideBackdop then
|
||
|
|
local alpha = ModelScene.GreyBackdrop:GetAlpha();
|
||
|
|
if alpha ~= 1 then
|
||
|
|
UIFrameFadeIn(ModelScene.GreyBackdrop, 1.5, alpha, 1);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
local alpha = ModelScene.GreyBackdrop:GetAlpha();
|
||
|
|
if alpha ~= 0 then
|
||
|
|
UIFrameFadeIn(ModelScene.GreyBackdrop, 1.0, alpha, 0);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if central then
|
||
|
|
finalYaw = 0;
|
||
|
|
frame.toYaw = YAW_FACING_FORWARD;
|
||
|
|
if index == 6 then
|
||
|
|
--Outfit fully collected
|
||
|
|
toActorX, toActorY = -(modelXSize3D + BOUNDING_BOX_DISTANCE)/2, 0;
|
||
|
|
After(0.1, function()
|
||
|
|
Actor2EnterScene();
|
||
|
|
end)
|
||
|
|
else
|
||
|
|
toActorX, toActorY = 0, 0;
|
||
|
|
end
|
||
|
|
panningOffsets = PANNING_OFFSETS_FULL_CENTRAL;
|
||
|
|
finalZoom = 5.5;
|
||
|
|
|
||
|
|
closeUp = false;
|
||
|
|
if closeUp ~= self.isCloseUp then
|
||
|
|
self.isCloseUp = closeUp;
|
||
|
|
local Backdrop2 = ModelScene.Backdrop2;
|
||
|
|
local Backdrop = ModelScene.Backdrop;
|
||
|
|
local BackdropBlur = ModelScene.BackdropBlur;
|
||
|
|
local alpha = Backdrop2:GetAlpha();
|
||
|
|
UIFrameFadeIn(Backdrop2, 1.5, alpha, 0);
|
||
|
|
UIFrameFadeIn(Backdrop, 1.5, alpha, 0);
|
||
|
|
UIFrameFadeIn(BackdropBlur, 1.5, 1-alpha, 0);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
finalYaw = 0.52;
|
||
|
|
toActorX, toActorY = 0, 0;
|
||
|
|
|
||
|
|
local Backdrop2 = ModelScene.Backdrop2;
|
||
|
|
local Backdrop = ModelScene.Backdrop;
|
||
|
|
local BackdropBlur = ModelScene.BackdropBlur;
|
||
|
|
local updateBackdrop;
|
||
|
|
|
||
|
|
if closeUp ~= self.isCloseUp then
|
||
|
|
self.isCloseUp = closeUp;
|
||
|
|
updateBackdrop = true;
|
||
|
|
end
|
||
|
|
|
||
|
|
if closeUp then
|
||
|
|
finalZoom = 2.7;
|
||
|
|
if down then
|
||
|
|
panningOffsets = PANNING_OFFSETS_LOWER;
|
||
|
|
else
|
||
|
|
panningOffsets = PANNING_OFFSETS_UPPER;
|
||
|
|
end
|
||
|
|
|
||
|
|
if updateBackdrop then
|
||
|
|
local alpha = Backdrop2:GetAlpha();
|
||
|
|
UIFrameFadeIn(Backdrop2, duration, alpha, 0);
|
||
|
|
UIFrameFadeIn(Backdrop, duration, alpha, 0);
|
||
|
|
UIFrameFadeIn(BackdropBlur, duration, 1-alpha, 1);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
finalZoom = 4.2;
|
||
|
|
panningOffsets = PANNING_OFFSETS_FULL_RIGHT;
|
||
|
|
|
||
|
|
if updateBackdrop then
|
||
|
|
local alpha = Backdrop2:GetAlpha();
|
||
|
|
UIFrameFadeIn(Backdrop2, 1.5, alpha, 1);
|
||
|
|
UIFrameFadeIn(Backdrop, 1.5, alpha, 1);
|
||
|
|
UIFrameFadeIn(BackdropBlur, 1.5, 1 - alpha, 0);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if back ~= frame.lastFacing then
|
||
|
|
frame.lastFacing = back;
|
||
|
|
local animationIndex;
|
||
|
|
if back then
|
||
|
|
animationIndex = 2;
|
||
|
|
else
|
||
|
|
animationIndex = 3;
|
||
|
|
end
|
||
|
|
SetActorAnimation(actor, animationIndex);
|
||
|
|
After(0.65, function()
|
||
|
|
SetActorAnimation(actor, 1);
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
if back then
|
||
|
|
frame.toYaw = pi + YAW_FACING_FORWARD - finalYaw;
|
||
|
|
else
|
||
|
|
frame.toYaw = YAW_FACING_FORWARD - finalYaw;
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.isSecondActorVisible then
|
||
|
|
self.isSecondActorVisible = nil;
|
||
|
|
animActorMovement:Hide();
|
||
|
|
if self.secondActor then
|
||
|
|
FadeFrame(self.secondActor, 0.25, "OUT");
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
ModelSceneCamera.customDuration = duration;
|
||
|
|
frame.duration = duration;
|
||
|
|
|
||
|
|
local scaleFactor = self.scaleFactor or 1;
|
||
|
|
frame.fromX = ModelSceneCamera.panningXOffset;
|
||
|
|
frame.fromY = ModelSceneCamera.panningYOffset;
|
||
|
|
frame.toX = scaleFactor * panningOffsets[1];
|
||
|
|
frame.toY = scaleFactor * panningOffsets[2];
|
||
|
|
frame.fromYaw = actor:GetYaw();
|
||
|
|
frame.fromYaw = actor:GetYaw();
|
||
|
|
frame.fromActorX, frame.fromActorY = actor:GetPosition();
|
||
|
|
frame.toActorX, frame.toActorY = toActorX, toActorY;
|
||
|
|
|
||
|
|
frame:Show();
|
||
|
|
|
||
|
|
ModelSceneCamera.updateCamera = nil;
|
||
|
|
ModelSceneCamera.total = 0;
|
||
|
|
ModelSceneCamera.fromZoomDistance = ModelSceneCamera.interpolatedZoomDistance --ModelSceneCamera:GetInterpolatedZoomDistance();
|
||
|
|
ModelSceneCamera.toZoomDistance = finalZoom;
|
||
|
|
ModelSceneCamera.updateCamera = true;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
------------------------------------------------------------------
|
||
|
|
--Set List
|
||
|
|
local BaseSetData = {};
|
||
|
|
local VariantSetData = {};
|
||
|
|
|
||
|
|
local function HideSetList()
|
||
|
|
if ShowSetList(false) then
|
||
|
|
SetList.isActive = false;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function RefreshSetData()
|
||
|
|
local buttons = SetList.buttons;
|
||
|
|
local button;
|
||
|
|
local variants;
|
||
|
|
local setIDs = {};
|
||
|
|
local sort = table.sort;
|
||
|
|
local setInfo;
|
||
|
|
local baseSetID;
|
||
|
|
for i = 1, #buttons do
|
||
|
|
button = buttons[i];
|
||
|
|
baseSetID = button.setID;
|
||
|
|
variants = GetVariantSets(baseSetID);
|
||
|
|
|
||
|
|
wipe(setIDs);
|
||
|
|
setInfo = GetSetInfo(baseSetID);
|
||
|
|
tinsert(setIDs, {["setID"] = setInfo.setID, ["uiOrder"] = setInfo.uiOrder, ["isCollected"] = setInfo.collected} );
|
||
|
|
|
||
|
|
for j = 1, #variants do
|
||
|
|
setInfo = variants[j];
|
||
|
|
if setInfo.setID ~= baseSetID then
|
||
|
|
tinsert(setIDs, {["setID"] = setInfo.setID, ["uiOrder"] = setInfo.uiOrder, ["isCollected"] = setInfo.collected} );
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
sort(setIDs, function(a, b)
|
||
|
|
if ( a.uiOrder and b.uiOrder ) then
|
||
|
|
return a.uiOrder < b.uiOrder
|
||
|
|
end
|
||
|
|
return a.setID < b.setID;
|
||
|
|
end);
|
||
|
|
button:CreateSubSetIndicator(setIDs);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
NarciOutfitCardMixin = {};
|
||
|
|
|
||
|
|
function NarciOutfitCardMixin:OnClick()
|
||
|
|
if self.setID then
|
||
|
|
ModelScene:DisplaySet(self.setID);
|
||
|
|
HideSetList();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitCardMixin:OnEnter()
|
||
|
|
UIFrameFadeIn(self.Name, 0.15, self.Name:GetAlpha(), 1);
|
||
|
|
UIFrameFadeIn(self.Label, 0.15, self.Label:GetAlpha(), 0.66);
|
||
|
|
UIFrameFadeIn(self.Highlight, 0.25, self.Highlight:GetAlpha(), 1);
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitCardMixin:OnLeave()
|
||
|
|
UIFrameFadeIn(self.Name, 0.15, self.Name:GetAlpha(), 0.8);
|
||
|
|
UIFrameFadeIn(self.Label, 0.15, self.Label:GetAlpha(), 0.46);
|
||
|
|
UIFrameFadeIn(self.Highlight, 0.25, self.Highlight:GetAlpha(), 0);
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitCardMixin:CreateSubSetIndicator(variantInfo)
|
||
|
|
local numVariation = #variantInfo;
|
||
|
|
|
||
|
|
if not self.squares then
|
||
|
|
self.squares = {};
|
||
|
|
end
|
||
|
|
|
||
|
|
local icon;
|
||
|
|
for i = 1, #variantInfo do
|
||
|
|
if self.squares[i] then
|
||
|
|
icon = self.squares[i];
|
||
|
|
else
|
||
|
|
icon = self:CreateTexture(nil, "OVERLAY");
|
||
|
|
icon:SetSize(8, 8);
|
||
|
|
icon:SetTexture("Interface/AddOns/Narcissus/Art/Modules/Outfit/OptionSquare-Green", nil, nil, "TRILINEAR");
|
||
|
|
tinsert(self.squares, icon);
|
||
|
|
end
|
||
|
|
|
||
|
|
if variantInfo[i].isCollected then
|
||
|
|
icon:SetTexCoord(0.5, 1, 0, 1);
|
||
|
|
else
|
||
|
|
icon:SetTexCoord(0, 0.5, 0, 1);
|
||
|
|
end
|
||
|
|
|
||
|
|
icon:SetPoint("BOTTOM", self, "BOTTOM", 8 * (1 - numVariation)/2 + (i - 1)*8 , 16);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function CreateSetCard(frame)
|
||
|
|
local button, model;
|
||
|
|
local buttons, models = {}, {};
|
||
|
|
local numSet = #BaseSetData;
|
||
|
|
local data;
|
||
|
|
local sources;
|
||
|
|
local setID;
|
||
|
|
|
||
|
|
for i = 1, numSet do
|
||
|
|
button = CreateFrame("Button", nil, frame.ScrollChild, "Narci_OutfitCardTemplate");
|
||
|
|
tinsert(buttons, button);
|
||
|
|
if i == 1 then
|
||
|
|
button:SetPoint("TOPLEFT", frame.ScrollChild, "TOPLEFT", 0, 0);
|
||
|
|
else
|
||
|
|
button:SetPoint("TOPLEFT", buttons[i - 1], "TOPRIGHT", 0, 0);
|
||
|
|
end
|
||
|
|
data = BaseSetData[i];
|
||
|
|
setID = data.setID;
|
||
|
|
button.Name:SetText( GetSetConciseName(data.name) );
|
||
|
|
button.Label:SetText(data.label);
|
||
|
|
button.setID = setID;
|
||
|
|
button.isFavorite = data.favorite;
|
||
|
|
|
||
|
|
model = CreateFrame("DressUpModel", nil, frame.ModelContainer, "Narci_OufitCardModelTemplate");
|
||
|
|
tinsert(models, model);
|
||
|
|
button.model = model;
|
||
|
|
model:SetPoint("BOTTOM", button, "TOP", 0, 1);
|
||
|
|
if i <= 8 then
|
||
|
|
model:Show()
|
||
|
|
end
|
||
|
|
|
||
|
|
sources = GetSetSources(setID);
|
||
|
|
model.sources = sources;
|
||
|
|
end
|
||
|
|
|
||
|
|
frame.buttons = buttons;
|
||
|
|
frame.ModelContainer.models = models;
|
||
|
|
|
||
|
|
return numSet
|
||
|
|
end
|
||
|
|
|
||
|
|
function SetCaredModelOffset(x, y, zoom)
|
||
|
|
local model = SetListModel.models[1];
|
||
|
|
MODEL1 = model;
|
||
|
|
if x and y then
|
||
|
|
model:SetViewTranslation(x, y);
|
||
|
|
end
|
||
|
|
if zoom then
|
||
|
|
model:SetPortraitZoom(zoom);
|
||
|
|
model:MakeCurrentCameraCustom();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function SetList_ToggleList(self)
|
||
|
|
if not SetList.isActive then
|
||
|
|
if ShowSetList(true) then
|
||
|
|
SetList.isActive = true;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function SetList_OnMouseDown(self)
|
||
|
|
if ShowSetList(not self.isActive) then
|
||
|
|
self.isActive = not self.isActive;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function SetList_OnLoad(self)
|
||
|
|
--Acquire All Set Data
|
||
|
|
BaseSetData = GetBaseSets();
|
||
|
|
local comparison = function(set1, set2)
|
||
|
|
--[[
|
||
|
|
local groupFavorite1 = set1.favoriteSetID and true;
|
||
|
|
local groupFavorite2 = set2.favoriteSetID and true;
|
||
|
|
if ( groupFavorite1 ~= groupFavorite2 ) then
|
||
|
|
return groupFavorite1;
|
||
|
|
end
|
||
|
|
--]]
|
||
|
|
--[[
|
||
|
|
if ( set1.favorite ~= set2.favorite ) then
|
||
|
|
return set1.favorite;
|
||
|
|
end
|
||
|
|
--]]
|
||
|
|
local reverseUIOrder = true
|
||
|
|
if ( set1.expansionID ~= set2.expansionID ) then
|
||
|
|
return set1.expansionID > set2.expansionID;
|
||
|
|
end
|
||
|
|
if not ignorePatchID then
|
||
|
|
if ( set1.patchID ~= set2.patchID ) then
|
||
|
|
return set1.patchID > set2.patchID;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if ( set1.uiOrder ~= set2.uiOrder ) then
|
||
|
|
if ( reverseUIOrder ) then
|
||
|
|
return set1.uiOrder < set2.uiOrder;
|
||
|
|
else
|
||
|
|
return set1.uiOrder > set2.uiOrder;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if reverseUIOrder then
|
||
|
|
return set1.setID < set2.setID;
|
||
|
|
else
|
||
|
|
return set1.setID > set2.setID;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
table.sort(BaseSetData, comparison);
|
||
|
|
|
||
|
|
|
||
|
|
local numButton = CreateSetCard(self);
|
||
|
|
RefreshSetData();
|
||
|
|
|
||
|
|
--Scroll Frame
|
||
|
|
local BUTTON_PER_PAGE = 5;
|
||
|
|
local BUTTON_PER_SCROLL = 1;
|
||
|
|
local buttonHeight = 171; --Use the width because it scrolls horizontally
|
||
|
|
local totalHeight = floor(numButton * buttonHeight + 0.5);
|
||
|
|
local maxScroll = floor((numButton - BUTTON_PER_PAGE) * buttonHeight + 0.5);
|
||
|
|
local scrollBar = self.scrollBar;
|
||
|
|
scrollBar:SetMinMaxValues(0, max(maxScroll, 0) )
|
||
|
|
scrollBar:SetValueStep(0.001);
|
||
|
|
self.buttonHeight = totalHeight;
|
||
|
|
self.range = maxScroll;
|
||
|
|
|
||
|
|
scrollBar:Disable();
|
||
|
|
scrollBar.nextIndex = 0;
|
||
|
|
|
||
|
|
local ceil = math.ceil;
|
||
|
|
|
||
|
|
local function UpdateRenderRange(self, buttonIndex)
|
||
|
|
if buttonIndex > self.nextIndex then
|
||
|
|
local index = ceil(buttonIndex);
|
||
|
|
self.nextIndex = index;
|
||
|
|
SetListModel.models[index]:Show();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
scrollBar:SetScript("OnValueChanged", function(self, value)
|
||
|
|
self:GetParent():SetHorizontalScroll(value);
|
||
|
|
local buttonPosition = value/171 + BUTTON_PER_PAGE
|
||
|
|
UpdateRenderRange(self, buttonPosition)
|
||
|
|
--UpdateInnerShadowStates(self, nil, false);
|
||
|
|
end)
|
||
|
|
NarciAPI_SmoothScroll_Initialization(self, nil, nil, BUTTON_PER_SCROLL/(numButton), 0.2, nil, SetList_ToggleList);
|
||
|
|
|
||
|
|
self:SetVerticalScroll(-VERTICAL_SCROLL);
|
||
|
|
end
|
||
|
|
------------------------------------------------------------------
|
||
|
|
NarciOutfitNavigationButtonMixin = {}
|
||
|
|
|
||
|
|
local NUM_LEVEL = 4;
|
||
|
|
local navigationStrutcure = {
|
||
|
|
[1] = {
|
||
|
|
["name"] = "Outfit",
|
||
|
|
["scriptType"] = 1,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
for i = 2, NUM_LEVEL do
|
||
|
|
navigationStrutcure[i] = {};
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function NarciOutfitNavigationButtonMixin:OnEnter()
|
||
|
|
if self.isCurrent then
|
||
|
|
self.Label:SetTextColor(1, 1, 1);
|
||
|
|
else
|
||
|
|
self.Label:SetTextColor(GRAY_20, GRAY_20, GRAY_20);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitNavigationButtonMixin:ResetTextColor()
|
||
|
|
if self.isCurrent then
|
||
|
|
self.Label:SetTextColor(GRAY_20, GRAY_20, GRAY_20);
|
||
|
|
else
|
||
|
|
self.Label:SetTextColor(GRAY_50, GRAY_50, GRAY_50);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitNavigationButtonMixin:OnLeave()
|
||
|
|
self:ResetTextColor();
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitNavigationButtonMixin:OnClick()
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitNavigationButtonMixin:SetLabel(text)
|
||
|
|
if text then
|
||
|
|
self.Label:SetText( upper(text) );
|
||
|
|
self:SetWidth(floor(self.Label:GetWidth() + 0.5) );
|
||
|
|
self:ResetTextColor();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
local function MoveNavigationButtonHighlight(self)
|
||
|
|
local buttons = self:GetParent().navigationButtons;
|
||
|
|
for _, button in pairs(buttons) do
|
||
|
|
button.isOn = nil;
|
||
|
|
button.Label:SetTextColor(GRAY_50, GRAY_50, GRAY_50);
|
||
|
|
end
|
||
|
|
self.isOn = true;
|
||
|
|
self.Label:SetTextColor(GRAY_20, GRAY_20, GRAY_20);
|
||
|
|
MoveHighlightTo(self.index);
|
||
|
|
end
|
||
|
|
|
||
|
|
local function CreateLeftTabNavigations(frame)
|
||
|
|
local function func1(self)
|
||
|
|
MoveNavigationButtonHighlight(self);
|
||
|
|
self:GetParent().Create:Show();
|
||
|
|
self:GetParent().ItemList:Hide();
|
||
|
|
|
||
|
|
NarciCamera:GoToCamera(1);
|
||
|
|
OutfitFrame:SetActiveTabIndex(1);
|
||
|
|
end
|
||
|
|
|
||
|
|
local function func2(self)
|
||
|
|
MoveNavigationButtonHighlight(self);
|
||
|
|
self:GetParent().Create:Hide();
|
||
|
|
local isOutfitComplete = self:GetParent().ItemList:UpdateSources(true);
|
||
|
|
|
||
|
|
OutfitFrame:SetActiveTabIndex(2);
|
||
|
|
|
||
|
|
local transitionDuration = 0.8;
|
||
|
|
if isOutfitComplete then
|
||
|
|
NarciCamera:GoToCamera(5, transitionDuration);
|
||
|
|
else
|
||
|
|
NarciCamera:GoToCamera(6, transitionDuration);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function func3(self)
|
||
|
|
MoveNavigationButtonHighlight(self);
|
||
|
|
self:GetParent().Create:Hide();
|
||
|
|
self:GetParent().ItemList:UpdateSources(false);
|
||
|
|
|
||
|
|
OutfitFrame:SetActiveTabIndex(3);
|
||
|
|
|
||
|
|
local transitionDuration = 0.8;
|
||
|
|
NarciCamera:GoToCamera(6, transitionDuration);
|
||
|
|
end
|
||
|
|
|
||
|
|
local LeftNavigations = {
|
||
|
|
--Order = {Button Text, Function}
|
||
|
|
[1] = {"Create", func1},
|
||
|
|
[2] = {"Collect", func2},
|
||
|
|
[3] = {"Share", func3},
|
||
|
|
};
|
||
|
|
|
||
|
|
local button;
|
||
|
|
local buttons = {};
|
||
|
|
for i = 1, #LeftNavigations do
|
||
|
|
button = CreateFrame("Button", nil, frame, "Narci_TabNavigationButtonTemplate");
|
||
|
|
tinsert(buttons, button);
|
||
|
|
if i == 1 then
|
||
|
|
button:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 0);
|
||
|
|
else
|
||
|
|
button:SetPoint("TOPLEFT", buttons[i - 1], "TOPRIGHT", 0, 0);
|
||
|
|
end
|
||
|
|
button.Label:SetText(LeftNavigations[i][1]);
|
||
|
|
button.index = i;
|
||
|
|
button:SetScript("OnClick", LeftNavigations[i][2]);
|
||
|
|
end
|
||
|
|
|
||
|
|
frame.navigationButtons = buttons;
|
||
|
|
frame.Navigation:SetWidth( button:GetWidth() * #LeftNavigations )
|
||
|
|
end
|
||
|
|
|
||
|
|
local function DisplayComponent(sources)
|
||
|
|
local appliedSourceIDs = {};
|
||
|
|
local slotID;
|
||
|
|
local slotButton;
|
||
|
|
local sourceInfo;
|
||
|
|
local cameraID;
|
||
|
|
local itemButtons = ItemModelTab.buttonBySlotID;
|
||
|
|
|
||
|
|
for sourceID, isCollected in pairs(sources) do
|
||
|
|
sourceInfo = GetSourceInfo(sourceID);
|
||
|
|
slotID = GetSlotForInventoryType(sourceInfo.invType);
|
||
|
|
slotButton = itemButtons[slotID];
|
||
|
|
appliedSourceIDs[slotID] = sourceID;
|
||
|
|
--[[
|
||
|
|
if slotButton then
|
||
|
|
|
||
|
|
slotButton.sourceID = sourceID;
|
||
|
|
slotButton.isFavorite = sourceInfo.isFavorite;
|
||
|
|
slotButton.isCollected = sourceInfo.isCollected;
|
||
|
|
slotButton.isUsable = true;
|
||
|
|
slotButton.visualID = sourceInfo.visualID;
|
||
|
|
slotButton:UpdateStatusIcon();
|
||
|
|
|
||
|
|
slotButton:Show();
|
||
|
|
slotButton:RefreshSlot();
|
||
|
|
end
|
||
|
|
--]]
|
||
|
|
end
|
||
|
|
|
||
|
|
OutfitFrame.appliedSourceIDs = appliedSourceIDs;
|
||
|
|
|
||
|
|
--[[
|
||
|
|
for slotID, button in pairs(itemButtons) do
|
||
|
|
if not appliedSourceIDs[slotID] then
|
||
|
|
button:Undress();
|
||
|
|
button.Label:Show();
|
||
|
|
button.LabelBackground:Show();
|
||
|
|
button:UpdateStatusIcon();
|
||
|
|
button:Show();
|
||
|
|
button:RefreshSlot();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
--]]
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
local function SelectActor(actorIndex)
|
||
|
|
local actor = ModelScene:GetNarciActor(actorIndex);
|
||
|
|
ModelScene:ShowTriggerArea(false);
|
||
|
|
ModelScene:FadeOutOtherActors(actorIndex);
|
||
|
|
ModelScene.activeActor = actor;
|
||
|
|
--Item List
|
||
|
|
DisplayComponent(actor.sources);
|
||
|
|
|
||
|
|
SetActorAnimation(actor, 1);
|
||
|
|
animCameraMovement.actor = actor;
|
||
|
|
animActorMovement.actor1 = actor;
|
||
|
|
local actor2Index;
|
||
|
|
if actorIndex == 2 then
|
||
|
|
actor2Index = 1;
|
||
|
|
else
|
||
|
|
actor2Index = 2;
|
||
|
|
end
|
||
|
|
local actor2 = ModelScene:GetNarciActor(actor2Index);
|
||
|
|
--actor2:SetFacing(YAW_FACING_FORWARD);
|
||
|
|
ModelScene.secondActor = actor2;
|
||
|
|
animActorMovement.actor2 = actor2;
|
||
|
|
NarciCamera.secondActor = actor2;
|
||
|
|
|
||
|
|
OutfitFrame:SetStructure(2, ModelScene.Name:GetText(), 1);
|
||
|
|
ShowLeftTab(true);
|
||
|
|
|
||
|
|
local back = false;
|
||
|
|
animCameraMovement.lastFacing = back;
|
||
|
|
|
||
|
|
NarciCamera:GoToCamera(1);
|
||
|
|
ItemModelTab:ReturnHome();
|
||
|
|
OutfitFrame:SetActiveTabIndex(1);
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
------------------------------------------------------------------
|
||
|
|
NarciOutfitModelSceneActorMixin = {};
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneActorMixin:SetAnimationData(animation, variation, animSpeed, timeOffsetSecs)
|
||
|
|
if not animation then return end;
|
||
|
|
self:SetAnimation(animation, variation, animSpeed, timeOffsetSecs);
|
||
|
|
self.animationData = {animation, variation, animSpeed, timeOffsetSecs};
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneActorMixin:GetAnimationData()
|
||
|
|
if self.animationData then
|
||
|
|
return unpack(self.animationData)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneActorMixin:MoveTo(x, y, z)
|
||
|
|
self:SetPosition(x, y, z);
|
||
|
|
self.hasMoved = true;
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneActorMixin:SetFacing(yaw)
|
||
|
|
if yaw > pi then
|
||
|
|
yaw = yaw - 2 * pi;
|
||
|
|
elseif yaw < - pi then
|
||
|
|
yaw = yaw + 2 * pi;
|
||
|
|
end
|
||
|
|
self:SetYaw(yaw);
|
||
|
|
self.hasMoved = true;
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneActorMixin:OnModelLoaded()
|
||
|
|
--/run Narci_Outfit.ModelScene.narciActor[1]:SetModelByFileID(123465)1611191
|
||
|
|
--/run
|
||
|
|
--if true then return end
|
||
|
|
self:SetUseCenterForOrigin(true, true, false);
|
||
|
|
self.hasBoundingBox = nil;
|
||
|
|
After(0, function()
|
||
|
|
local offsetX, offsetY = 0 , 0
|
||
|
|
local x, y, z = self:GetPosition();
|
||
|
|
local scale = self:GetScale();
|
||
|
|
local a, b, c, d, e, f = self:GetActiveBoundingBox();
|
||
|
|
local depth, width, height = abs(a - d), abs(b - e), abs(c - f);
|
||
|
|
|
||
|
|
local scaleX, scaleY = 1, 1;
|
||
|
|
local scaleModifier = max(-0.3774*depth + 1.3208, 0.75); --Kultiran 0.8
|
||
|
|
print("Model depth: "..depth);
|
||
|
|
|
||
|
|
local maxBoundingBoxWidth = maxBoundingBoxWidth * scaleModifier;
|
||
|
|
if width > maxBoundingBoxWidth then
|
||
|
|
scaleX = sqrt(maxBoundingBoxWidth / width);
|
||
|
|
height = height * scaleX;
|
||
|
|
end
|
||
|
|
|
||
|
|
if height > maxBoundingBoxHeight then
|
||
|
|
print("Over Height")
|
||
|
|
--print("EXP Height: "..maxBoundingBoxHeight)
|
||
|
|
scaleY = maxBoundingBoxHeight / height;
|
||
|
|
height = maxBoundingBoxHeight;
|
||
|
|
end
|
||
|
|
|
||
|
|
local finalScale = scaleX * scaleY;
|
||
|
|
|
||
|
|
depth = depth * finalScale;
|
||
|
|
width = width * finalScale;
|
||
|
|
|
||
|
|
|
||
|
|
self.centerOffsetY = depth/finalScale / 4;
|
||
|
|
self.modelCenter = y;
|
||
|
|
|
||
|
|
if modelYSize3D == -1 then
|
||
|
|
modelYSize3D = depth;
|
||
|
|
BOUNDING_BOX_DISTANCE = BOUNDING_BOX_DISTANCE/finalScale/scaleModifier;
|
||
|
|
end
|
||
|
|
if modelXSize3D == -1 then
|
||
|
|
modelXSize3D = width;
|
||
|
|
|
||
|
|
local ModelScene = self:GetParent();
|
||
|
|
local L = ModelScene:Project3DPointTo2D(width/2, 0, 0);
|
||
|
|
local R = ModelScene:Project3DPointTo2D(-width/2, 0, 0);
|
||
|
|
modelXSize2D = abs(L - R);
|
||
|
|
self.anchorPoint3D[4]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", L, 20);
|
||
|
|
self.anchorPoint3D[5]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", R, 20);
|
||
|
|
local _, B = ModelScene:Project3DPointTo2D(0, 0, 0);
|
||
|
|
local _, H = ModelScene:Project3DPointTo2D(0, 0, height);
|
||
|
|
modelYSize2D = abs(H - B);
|
||
|
|
end
|
||
|
|
|
||
|
|
print("Calculated Scale: "..finalScale)
|
||
|
|
self:SetScale(finalScale)
|
||
|
|
|
||
|
|
--Show Bounding Box
|
||
|
|
if true then return end
|
||
|
|
local hideAxis = false;
|
||
|
|
|
||
|
|
print("depth "..depth)
|
||
|
|
--x = x - depth/4
|
||
|
|
scale = finalScale
|
||
|
|
a, d = a + x, d + x;
|
||
|
|
b, e = b + y, e + y;
|
||
|
|
c, f = c + z, f + z;
|
||
|
|
a, b, c, d, e, f = a*scale, b*scale, c*scale, d*scale, e*scale, f*scale
|
||
|
|
|
||
|
|
local ModelScene = self:GetParent();
|
||
|
|
|
||
|
|
if not self.a1 then
|
||
|
|
local a1 = ModelScene:CreateActor();
|
||
|
|
a1:SetModelByFileID(397940);
|
||
|
|
self.a1 = a1
|
||
|
|
if hideAxis then
|
||
|
|
a1:Hide();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.a1:SetPosition(d, b, c);
|
||
|
|
self.bottomright = {d, b, c};
|
||
|
|
|
||
|
|
if not self.b3 then
|
||
|
|
local b3 = ModelScene:CreateActor();
|
||
|
|
b3:SetModelByFileID(397940);
|
||
|
|
self.b3 = b3;
|
||
|
|
if hideAxis then
|
||
|
|
b3:Hide();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.b3:SetPosition(d, e, f);
|
||
|
|
|
||
|
|
if not self.b1 then
|
||
|
|
local b1 = ModelScene:CreateActor();
|
||
|
|
b1:SetModelByFileID(397940);
|
||
|
|
self.b1 = b1;
|
||
|
|
if hideAxis then
|
||
|
|
b1:Hide();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.b1:SetPosition(a, b, f);
|
||
|
|
|
||
|
|
if not self.a2 then
|
||
|
|
local a2 = ModelScene:CreateActor();
|
||
|
|
a2:SetModelByFileID(397940);
|
||
|
|
self.a2 = a2;
|
||
|
|
if hideAxis then
|
||
|
|
a2:Hide();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.a2:SetPosition(a, b, c);
|
||
|
|
self.bottomleft = {a, b, c};
|
||
|
|
|
||
|
|
if not self.a3 then
|
||
|
|
local a3 = ModelScene:CreateActor();
|
||
|
|
a3:SetModelByFileID(397940);
|
||
|
|
self.a3 = a3;
|
||
|
|
if hideAxis then
|
||
|
|
a3:Hide();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.a3:SetPosition(d, b, c);
|
||
|
|
|
||
|
|
if not self.a4 then
|
||
|
|
local a4 = ModelScene:CreateActor();
|
||
|
|
a4:SetModelByFileID(397940);
|
||
|
|
self.a4 = a4;
|
||
|
|
if hideAxis then
|
||
|
|
a4:Hide();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.a4:SetPosition(a, e, c);
|
||
|
|
|
||
|
|
if not self.b4 then
|
||
|
|
local b4 = ModelScene:CreateActor();
|
||
|
|
b4:SetModelByFileID(397940);
|
||
|
|
self.b4 = b4;
|
||
|
|
if hideAxis then
|
||
|
|
b4:Hide();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.b4:SetPosition(d, b, f);
|
||
|
|
|
||
|
|
if not self.b2 then
|
||
|
|
local b2 = ModelScene:CreateActor();
|
||
|
|
b2:SetModelByFileID(397940);
|
||
|
|
self.b2 = b2;
|
||
|
|
if hideAxis then
|
||
|
|
b2:Hide();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.b2:SetPosition(a, e, f);
|
||
|
|
|
||
|
|
self.hasBoundingBox = true
|
||
|
|
end)
|
||
|
|
--/run Narci_Outfit.ModelScene.narciActor[1]:SetModelByFileID(197617)
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneActorMixin:OnUpdate(elapsed)
|
||
|
|
local alpha = self:GetAlpha();
|
||
|
|
if alpha < 0.2 then
|
||
|
|
alpha = 0;
|
||
|
|
end
|
||
|
|
self.groundShadow:SetAlpha(alpha);
|
||
|
|
|
||
|
|
--[[
|
||
|
|
local arrow = self.arrow;
|
||
|
|
if arrow then
|
||
|
|
local x0, y0, z0 = self:GetPosition();
|
||
|
|
local scale = self:GetScale();
|
||
|
|
local yaw = self:GetYaw();
|
||
|
|
local ax, ay, az = RotateByYaw( (x0 + arrow.offsetX) , (y0 + arrow.offsetY), (z0 + arrow.offsetZ), x0, y0, z0, yaw);
|
||
|
|
arrow:SetPosition(ax*2*scale, ay*2*scale, az*2*scale);
|
||
|
|
arrow:SetYaw(yaw)
|
||
|
|
local x1, y1, z1 = ModelScene:Project3DPointTo2D(ax, ay, az);
|
||
|
|
self.anchorPoint3D[1]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", x1, y1);
|
||
|
|
self.anchorPoint3D[1]:Show()
|
||
|
|
end
|
||
|
|
--]]
|
||
|
|
|
||
|
|
if false and not self.hasMoved then return end
|
||
|
|
|
||
|
|
self.t = self.t + elapsed;
|
||
|
|
local x, y, z = self:GetPosition();
|
||
|
|
local yaw = self:GetYaw();
|
||
|
|
if self.t > 0.5 then
|
||
|
|
self.t = 0;
|
||
|
|
if y ~= self.lastY then
|
||
|
|
self.lastY = y;
|
||
|
|
elseif yaw ~= self.lastYaw then
|
||
|
|
self.lastYaw = yaw;
|
||
|
|
else
|
||
|
|
self.hasMoved = nil;
|
||
|
|
return
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local ModelScene = self:GetParent();
|
||
|
|
local scale = self:GetScale();
|
||
|
|
|
||
|
|
if self.centerOffsetY then
|
||
|
|
x, y, z = RotateByYaw(x + self.centerOffsetY, y, z, x, y, z, yaw);
|
||
|
|
end
|
||
|
|
|
||
|
|
x = x * scale;
|
||
|
|
y = y * scale;
|
||
|
|
z = z * scale;
|
||
|
|
|
||
|
|
local modelXSize3D = modelXSize3D * scale;
|
||
|
|
local modelYSize3D = modelYSize3D * scale;
|
||
|
|
|
||
|
|
local x1, y1, z1 = ModelScene:Project3DPointTo2D(x, y, z); --bottom center
|
||
|
|
self.anchorPoint3D[1]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", x1, y1);
|
||
|
|
|
||
|
|
local x2, y2, z2 = RotateByYaw((x - modelXSize3D/2) , (y + modelYSize3D/2) , z, x, y, z, yaw); --bottom left
|
||
|
|
x2, y2, z2 = ModelScene:Project3DPointTo2D(x2, y2, z2); --bottomleft
|
||
|
|
self.anchorPoint3D[2]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", x2, y2);
|
||
|
|
|
||
|
|
local x3, y3, z3 = RotateByYaw((x - modelXSize3D/2) , (y - modelYSize3D/2) , z, x, y, z, yaw); --bottom right
|
||
|
|
x3, y3, z3 = ModelScene:Project3DPointTo2D(x3, y3, z3);
|
||
|
|
self.anchorPoint3D[3]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", x3, y3);
|
||
|
|
|
||
|
|
local x4, y4, z4 = RotateByYaw((x + modelXSize3D/2) , (y - modelYSize3D/2) , z, x, y, z, yaw); --top right
|
||
|
|
x4, y4, z4 = ModelScene:Project3DPointTo2D(x4, y4, z4);
|
||
|
|
self.anchorPoint3D[4]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", x4, y4);
|
||
|
|
|
||
|
|
local x5, y5, z5 = RotateByYaw((x + modelXSize3D/2) , (y + modelYSize3D/2) , z, x, y, z, yaw); --top left
|
||
|
|
x5, y5, z5 = ModelScene:Project3DPointTo2D(x5, y5, z5);
|
||
|
|
self.anchorPoint3D[5]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", x5, y5);
|
||
|
|
|
||
|
|
local left = min(x2, x3, x4, x5);
|
||
|
|
local right = max(x2, x3, x4, x5);
|
||
|
|
local top = max(y2, y3, y4, y5);
|
||
|
|
local bottom = min(y2, y3, y4, y5);
|
||
|
|
local x0 = (left + right)/2;
|
||
|
|
self.x0 = x0;
|
||
|
|
self.anchorPoint3D[0]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", x0 , y1);
|
||
|
|
|
||
|
|
|
||
|
|
local shadowWidth = 1.25*max(right - left, top - bottom);
|
||
|
|
self.groundShadow:SetSize(shadowWidth, shadowWidth/2);
|
||
|
|
|
||
|
|
|
||
|
|
if false and self.hasBoundingBox then
|
||
|
|
local a, b, c = ModelScene:Project3DPointTo2D( unpack(self.bottomleft) );
|
||
|
|
self.anchorPoint3D[4]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", a, b);
|
||
|
|
a, b, c = ModelScene:Project3DPointTo2D( unpack(self.bottomright) );
|
||
|
|
self.anchorPoint3D[5]:SetPoint("CENTER", ModelScene, "BOTTOMLEFT", a, b);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
NarciOutfitModelSceneMixin = CreateFromMixins(PanningModelSceneMixin);
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:OnLoadNew()
|
||
|
|
self:OnLoad()
|
||
|
|
local _, _, raceID = UnitRace("player");
|
||
|
|
local isWorgen = (raceID == 22);
|
||
|
|
if isWorgen then
|
||
|
|
self.isWorgen = true;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:OnSizeChanged(width, height)
|
||
|
|
self.WorgenPreview:SetWidth(height);
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:GetActiveActor()
|
||
|
|
return self.activeActor
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:GetSecondActor()
|
||
|
|
return self.secondActor
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:GetNarciActor(index, preload)
|
||
|
|
if not self.narciActor then
|
||
|
|
self.narciActor = {};
|
||
|
|
end
|
||
|
|
|
||
|
|
if not index then return end
|
||
|
|
|
||
|
|
if not self.narciActor[index] then
|
||
|
|
local actor = self:CreateActor(nil, "NarciOutfitModelSceneActorTemplate");
|
||
|
|
|
||
|
|
actor:SetModelByUnit("player");
|
||
|
|
actor:SetAnimationBlendOperation(2); --Smooth Transition
|
||
|
|
actor:Undress();
|
||
|
|
actor:SetScale(1);
|
||
|
|
actor:SetFacing(-pi);
|
||
|
|
actor.index = index;
|
||
|
|
actor.t = 0; --Update Timer
|
||
|
|
self.narciActor[index] = actor;
|
||
|
|
|
||
|
|
if self.isWorgen then
|
||
|
|
local _, inHumanForm = HasAlternateForm();
|
||
|
|
actor.inHumanForm = inHumanForm;
|
||
|
|
self.inHumanForm = inHumanForm;
|
||
|
|
if inHumanForm then
|
||
|
|
self.humanActor = actor;
|
||
|
|
else
|
||
|
|
self.worgenActor = actor;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
--3D Points for Reference
|
||
|
|
actor.anchorPoint3D = {};
|
||
|
|
for i = 0, 5 do
|
||
|
|
local point = self:CreateTexture(nil, "OVERLAY", "NarciModelScene3DPointTemplate");
|
||
|
|
actor.anchorPoint3D[i] = point;
|
||
|
|
if i == 4 or i == 5 then
|
||
|
|
--Visual Center
|
||
|
|
point:SetColorTexture(0, 1, 0);
|
||
|
|
end
|
||
|
|
--point:Show()
|
||
|
|
end
|
||
|
|
|
||
|
|
local shadow = self:CreateTexture(nil, "BACKGROUND", "Narci_OutfitModelGroundshadowTemplate", 1);
|
||
|
|
|
||
|
|
actor.groundShadow = shadow;
|
||
|
|
shadow:ClearAllPoints();
|
||
|
|
shadow:SetPoint("CENTER", actor.anchorPoint3D[0], "CENTER", 0, 0);
|
||
|
|
|
||
|
|
if preload then
|
||
|
|
actor:SetAlpha(0);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return self.narciActor[index]
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:GetAlternateActor(forcedHumanForm)
|
||
|
|
if self.isWorgen then
|
||
|
|
if self.activeActor then
|
||
|
|
local goal;
|
||
|
|
if forcedHumanForm == nil then
|
||
|
|
goal = not self.inHumanForm;
|
||
|
|
else
|
||
|
|
goal = forcedHumanForm;
|
||
|
|
print("Force Changed")
|
||
|
|
end
|
||
|
|
|
||
|
|
if goal then
|
||
|
|
self.WorgenPreview:Hide();
|
||
|
|
--Return Human
|
||
|
|
if self.humanActor then
|
||
|
|
self.inHumanForm = true;
|
||
|
|
return self.humanActor;
|
||
|
|
else
|
||
|
|
local _, inHumanForm = HasAlternateForm();
|
||
|
|
if inHumanForm then
|
||
|
|
local actor = self:GetNarciActor(11);
|
||
|
|
self.inHumanForm = true;
|
||
|
|
return actor
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else
|
||
|
|
--Return Worgen
|
||
|
|
if self.worgenActor then
|
||
|
|
self.inHumanForm = false;
|
||
|
|
return self.worgenActor
|
||
|
|
else
|
||
|
|
local _, inHumanForm = HasAlternateForm();
|
||
|
|
if inHumanForm then
|
||
|
|
self.WorgenPreview:Show();
|
||
|
|
else
|
||
|
|
self.WorgenPreview:Hide();
|
||
|
|
self.WorgenPreview.Image:SetTexture(nil);
|
||
|
|
local actor = self:GetNarciActor(11);
|
||
|
|
self.inHumanForm = false;
|
||
|
|
return actor
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
else
|
||
|
|
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:SwitchToAlternateActor(forcedHumanForm)
|
||
|
|
local actor = self:GetAlternateActor(forcedHumanForm);
|
||
|
|
if actor then
|
||
|
|
print("Has Actor")
|
||
|
|
WORGENACTOR = actor
|
||
|
|
self:DuplicateActor(self.activeActor, actor);
|
||
|
|
self.activeActor = actor;
|
||
|
|
animCameraMovement.actor = actor;
|
||
|
|
animActorMovement.actor1 = actor;
|
||
|
|
else
|
||
|
|
if self.activeActor then
|
||
|
|
self.activeActor:Hide();
|
||
|
|
print("Alternate form was not set")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:DuplicateActor(actor, newActor)
|
||
|
|
local x, y, z = actor:GetPosition();
|
||
|
|
local yaw = actor:GetYaw();
|
||
|
|
local animation, variation, speed = actor:GetAnimationData();
|
||
|
|
newActor:SetPosition(x, y, z);
|
||
|
|
newActor:SetFacing(yaw);
|
||
|
|
newActor:SetSheathed( actor:GetSheathed() );
|
||
|
|
local newActorAnimation = newActor:GetAnimationData()
|
||
|
|
if animation ~= newActorAnimation then
|
||
|
|
newActor:SetAnimationData(animation, variation, speed);
|
||
|
|
end
|
||
|
|
|
||
|
|
local sourceID;
|
||
|
|
local appliedSourceIDs = self:GetParent().appliedSourceIDs;
|
||
|
|
for slotID, sourceID in pairs(appliedSourceIDs) do
|
||
|
|
local slotSource = newActor:GetSlotTransmogSources(slotID);
|
||
|
|
if slotSource ~= sourceID then
|
||
|
|
if slotID == 16 then
|
||
|
|
newActor:TryOn(sourceID, "MAINHANDSLOT", 0);
|
||
|
|
elseif slotID == 17 then
|
||
|
|
newActor:TryOn(sourceID, "SECONDARYHANDSLOT", 0);
|
||
|
|
else
|
||
|
|
newActor:TryOn(sourceID)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
--
|
||
|
|
FadeFrame(actor, 0.15, "OUT");
|
||
|
|
newActor:Show();
|
||
|
|
newActor.groundShadow:Show();
|
||
|
|
newActor.groundShadow:SetAlpha(1);
|
||
|
|
newActor:SetAlpha(1);
|
||
|
|
|
||
|
|
print("#1 IsHuman: "..tostring(actor.inHumanForm) )
|
||
|
|
print("#2 IsHuman: "..tostring(newActor.inHumanForm) )
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:GetNarciActorAndFinalPosition(actorIndex)
|
||
|
|
local actor = self:GetNarciActor(actorIndex);
|
||
|
|
local numVariation = 2;
|
||
|
|
local targetOffsetsY = ACTOR_POSITIONS[numVariation][1][2];
|
||
|
|
local facings = ACTOR_POSITIONS[numVariation][2];
|
||
|
|
actor:SetFacing(YAW_FACING_FORWARD);
|
||
|
|
|
||
|
|
return actor, targetOffsetsY
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:GetTriggerArea(actorIndex)
|
||
|
|
if not self.triggerAreas then
|
||
|
|
self.triggerAreas = CreateFrame("Frame", nil, self);
|
||
|
|
end
|
||
|
|
|
||
|
|
if not self.triggerAreas[actorIndex] then
|
||
|
|
local triggerArea = CreateFrame("Button", nil, self.triggerAreas);
|
||
|
|
self.triggerAreas[actorIndex] = triggerArea;
|
||
|
|
triggerArea.actorIndex = actorIndex;
|
||
|
|
triggerArea.actor = self.narciActor[actorIndex];
|
||
|
|
|
||
|
|
triggerArea:SetHeight(1200);
|
||
|
|
|
||
|
|
triggerArea:SetScript("OnEnter", function(self)
|
||
|
|
SetActorAnimation(self.actor, 4);
|
||
|
|
end)
|
||
|
|
triggerArea:SetScript("OnLeave", function(self)
|
||
|
|
SetActorAnimation(self.actor, 0);
|
||
|
|
end)
|
||
|
|
triggerArea:SetScript("OnClick", function(self)
|
||
|
|
SelectActor(self.actorIndex);
|
||
|
|
end)
|
||
|
|
|
||
|
|
local tex = triggerArea:CreateTexture(nil, "OVERLAY");
|
||
|
|
local r = math.random();
|
||
|
|
tex:SetAllPoints(true)
|
||
|
|
tex:SetColorTexture(r, 1 - r, 1 - r, 0.5);
|
||
|
|
tex:Hide();
|
||
|
|
|
||
|
|
return triggerArea
|
||
|
|
else
|
||
|
|
return self.triggerAreas[actorIndex]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:UpdateTriggerArea()
|
||
|
|
if modelXSize2D == -1 then return end
|
||
|
|
local scaleFactor = self:GetParent().scaleFactor or 1;
|
||
|
|
local actor, triggerArea;
|
||
|
|
for i = 1, #self.narciActor do
|
||
|
|
if i > 5 then return end
|
||
|
|
|
||
|
|
actor = self.narciActor[i];
|
||
|
|
if actor then
|
||
|
|
triggerArea = self:GetTriggerArea(i);
|
||
|
|
if actor:IsShown() then
|
||
|
|
print(actor.index)
|
||
|
|
local center = actor.x0;
|
||
|
|
if not self.triggerAreaSize then
|
||
|
|
self.triggerAreaSize = {};
|
||
|
|
end
|
||
|
|
self.triggerAreaSize[i] = {center - modelXSize2D/2, center + modelXSize2D/2};
|
||
|
|
triggerArea:SetWidth(modelXSize2D * scaleFactor);
|
||
|
|
triggerArea:SetPoint("BOTTOM", self, "BOTTOMLEFT", center, 80);
|
||
|
|
triggerArea:Show();
|
||
|
|
else
|
||
|
|
triggerArea:Hide();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:ShowTriggerArea(visible)
|
||
|
|
if self.triggerAreas then
|
||
|
|
self.triggerAreas:SetShown(visible);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:SetLabel(name, label)
|
||
|
|
if not name then return end;
|
||
|
|
|
||
|
|
name = GetSetConciseName(name);
|
||
|
|
self.Name:SetText(name);
|
||
|
|
self.Label:SetText(label);
|
||
|
|
self.TextFrame:Show();
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:HideGroundShadows()
|
||
|
|
if self.shadows then
|
||
|
|
for _, shadow in pairs(self.shadows) do
|
||
|
|
shadow:Hide();
|
||
|
|
shadow:SetAlpha(0);
|
||
|
|
if shadow.fadeInfo then
|
||
|
|
shadow.fadeInfo.endAlpha = 0;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
NarciCamera.isGroundShadowVisible = nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
--[[
|
||
|
|
function NarciOutfitModelSceneMixin:ShowGroundShadow(numActor, smoothing)
|
||
|
|
if not self.shadows then
|
||
|
|
self.shadows = {};
|
||
|
|
end
|
||
|
|
local shadows = self.shadows;
|
||
|
|
local shadow;
|
||
|
|
local offsets = SHADOW_POSITIONS[numActor];
|
||
|
|
|
||
|
|
local numActor = 1 --
|
||
|
|
|
||
|
|
for i = 1, numActor do
|
||
|
|
shadow = shadows[i];
|
||
|
|
if not shadow then
|
||
|
|
shadow = self:CreateTexture(nil, "BACKGROUND", "Narci_OutfitModelGroundshadowTemplate");
|
||
|
|
tinsert(shadows, shadow);
|
||
|
|
local actor = self:GetNarciActor(i);
|
||
|
|
actor.groundShadow = shadow;
|
||
|
|
shadow:ClearAllPoints();
|
||
|
|
shadow:SetPoint("CENTER", self.AnchorPoint0, "CENTER", 0, 0);
|
||
|
|
--shadow:SetPoint("BOTTOMRIGHT", self.AnchorPoint2)
|
||
|
|
end
|
||
|
|
|
||
|
|
--shadow:SetPoint("BOTTOM", self, "BOTTOM", offsets[i], 60);
|
||
|
|
if smoothing then
|
||
|
|
FadeFrame(shadow, 1, "IN");
|
||
|
|
else
|
||
|
|
shadow:Show();
|
||
|
|
shadow:SetAlpha(1);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
for i = numActor + 1, #shadows do
|
||
|
|
shadows[i]:Hide();
|
||
|
|
end
|
||
|
|
|
||
|
|
NarciCamera.isGroundShadowVisible = true;
|
||
|
|
end
|
||
|
|
--]]
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:HideOtherActors(numHidden)
|
||
|
|
if not numHidden then return end
|
||
|
|
|
||
|
|
if self.narciActor then
|
||
|
|
for _, actor in pairs(self.narciActor) do
|
||
|
|
if actor.index > numHidden then
|
||
|
|
actor:Hide();
|
||
|
|
actor.groundShadow:Hide();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:FadeOutOtherActors(actorIndex)
|
||
|
|
if self.narciActor then
|
||
|
|
for _, actor in pairs(self.narciActor) do
|
||
|
|
if actor.index ~= actorIndex then
|
||
|
|
FadeFrame(actor, 0.15, "OUT");
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
FadeFrame(self.TextFrame, 0.25, "OUT");
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:DisplaySet(baseSetID)
|
||
|
|
--Set Data
|
||
|
|
local setInfo = GetSetInfo(baseSetID);
|
||
|
|
self:SetLabel("vengeance" or setInfo.name, setInfo.label);
|
||
|
|
|
||
|
|
local variants = GetVariantSets(baseSetID);
|
||
|
|
local setID;
|
||
|
|
local setIDs = {};
|
||
|
|
local uiOrder = setInfo.uiOrder;
|
||
|
|
tinsert(setIDs, {["setID"] = baseSetID, ["uiOrder"] = uiOrder} );
|
||
|
|
|
||
|
|
for i = 1, #variants do
|
||
|
|
setInfo = variants[i];
|
||
|
|
if setInfo then
|
||
|
|
setID = setInfo.setID;
|
||
|
|
if setID ~= baseSetID then
|
||
|
|
uiOrder = setInfo.uiOrder;
|
||
|
|
tinsert(setIDs, {["setID"] = setID, ["uiOrder"] = uiOrder} );
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
table.sort(setIDs, function(a, b)
|
||
|
|
if ( a.uiOrder and b.uiOrder ) then
|
||
|
|
return a.uiOrder > b.uiOrder
|
||
|
|
end
|
||
|
|
|
||
|
|
return a.setID > b.setID;
|
||
|
|
end);
|
||
|
|
|
||
|
|
local numVariation = #setIDs;
|
||
|
|
local sources;
|
||
|
|
local actor;
|
||
|
|
local offsetsY = ACTOR_POSITIONS[numVariation][1];
|
||
|
|
local facings = ACTOR_POSITIONS[numVariation][2];
|
||
|
|
local offsetsX = ACTOR_POSITIONS_INWARD[numVariation];
|
||
|
|
|
||
|
|
local sourceInfo, slot, slotSources;
|
||
|
|
|
||
|
|
|
||
|
|
--Actor
|
||
|
|
self:HideOtherActors(numVariation);
|
||
|
|
|
||
|
|
local actors = {};
|
||
|
|
for i = 1, numVariation do
|
||
|
|
--Position
|
||
|
|
actor = self:GetNarciActor(i);
|
||
|
|
SetActorAnimation(actor, 0);
|
||
|
|
actor:MoveTo(offsetsX[i], offsetsY[i], 0);
|
||
|
|
actor:SetFacing(facings[i]);
|
||
|
|
--print(facings[i])
|
||
|
|
actor:SetAlpha(0);
|
||
|
|
tinsert(actors, actor);
|
||
|
|
actor:Undress();
|
||
|
|
|
||
|
|
--Dress Up
|
||
|
|
local collectedSources = {};
|
||
|
|
setID = setIDs[i]["setID"];
|
||
|
|
sources = GetSetSources(setID);
|
||
|
|
|
||
|
|
for sourceID, isCollected in pairs(sources) do
|
||
|
|
actor:TryOn(sourceID);
|
||
|
|
sourceInfo = C_TransmogCollection.GetSourceInfo(sourceID);
|
||
|
|
slot = C_Transmog.GetSlotForInventoryType(sourceInfo.invType);
|
||
|
|
slotSources = C_TransmogSets.GetSourcesForSlot(setID, slot);
|
||
|
|
|
||
|
|
local isVisualCollected;
|
||
|
|
|
||
|
|
for index, info in pairs(slotSources) do
|
||
|
|
if info.isCollected then
|
||
|
|
isVisualCollected = true;
|
||
|
|
collectedSources[info.sourceID] = true;
|
||
|
|
break
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if not isVisualCollected then
|
||
|
|
collectedSources[sourceID] = false;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
actor.sources = collectedSources;
|
||
|
|
|
||
|
|
--actor:UndressSlot(1) --Helm Off
|
||
|
|
actor:Show();
|
||
|
|
actor.groundShadow:Show();
|
||
|
|
ACTOR = actor;
|
||
|
|
end
|
||
|
|
|
||
|
|
ModelSceneCamera.interpolatedZoomDistance = 4.5;
|
||
|
|
ModelSceneCamera:SnapAllInterpolatedValues();
|
||
|
|
After(0, function()
|
||
|
|
ModelSceneCamera.interpolatedZoomDistance = 5.5;
|
||
|
|
self:ReCalculatePosition(numVariation);
|
||
|
|
After(0, function()
|
||
|
|
self:UpdateTriggerArea();
|
||
|
|
end)
|
||
|
|
end)
|
||
|
|
|
||
|
|
for _, actor in pairs(actors) do
|
||
|
|
UIFrameFadeIn(actor, 0.25, 0, 1);
|
||
|
|
end
|
||
|
|
--self:ShowGroundShadow(numVariation);
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:ReCalculatePosition(numActor)
|
||
|
|
local actor;
|
||
|
|
local actors = ModelScene.narciActor;
|
||
|
|
local modelXSize3D = modelXSize3D;
|
||
|
|
|
||
|
|
for i = 1, #actors do
|
||
|
|
actor = actors[i];
|
||
|
|
local newCenter
|
||
|
|
if i == 1 then
|
||
|
|
print(actor.modelCenter)
|
||
|
|
newCenter = (modelXSize3D + BOUNDING_BOX_DISTANCE) * (numActor - 1)/2
|
||
|
|
actor:MoveTo(newCenter, 0, 0);
|
||
|
|
actor.modelCenter = newCenter;
|
||
|
|
else
|
||
|
|
newCenter = actors[i - 1].modelCenter - modelXSize3D - BOUNDING_BOX_DISTANCE;
|
||
|
|
actor.modelCenter = newCenter;
|
||
|
|
actor:MoveTo(newCenter, 0, 0 )
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:Initialize()
|
||
|
|
local CAMERA_DEFAULT_PITCH = 0 -- -pi/40;
|
||
|
|
local CAMERA_DEFAULT_YAW = pi/2;
|
||
|
|
ModelScene = self;
|
||
|
|
|
||
|
|
self.Name = self.TextFrame.Name;
|
||
|
|
self.Label = self.TextFrame.Label;
|
||
|
|
self.Name:SetTextColor(GRAY_20, GRAY_20, GRAY_20);
|
||
|
|
self.Label:SetTextColor(GRAY_50, GRAY_50, GRAY_50);
|
||
|
|
|
||
|
|
self:TransitionToModelSceneID(290, CAMERA_TRANSITION_TYPE_IMMEDIATE, CAMERA_MODIFICATION_TYPE_DISCARD, true);
|
||
|
|
|
||
|
|
--Camera Setting
|
||
|
|
local camera = self:GetActiveCamera();
|
||
|
|
camera.maxZoomDistance = 5.5;
|
||
|
|
--camera:SetZoomDistance(5.5);
|
||
|
|
camera.interpolatedZoomDistance = 5.5;
|
||
|
|
camera.zoomInterpolationAmount = 0.06--(ZOOM_DISTANCE_FAR - ZOOM_DISTANCE_CLOSE) / BLEND_DURATION; --0.15
|
||
|
|
ModelSceneCamera = camera;
|
||
|
|
self.narciCamera = camera;
|
||
|
|
CAMERA = camera; --global test
|
||
|
|
|
||
|
|
camera:SetYaw(CAMERA_DEFAULT_YAW);
|
||
|
|
camera:SetPitch(CAMERA_DEFAULT_PITCH);
|
||
|
|
camera.interpolatedYaw = pi/2;
|
||
|
|
camera.interpolatedPitch = CAMERA_DEFAULT_PITCH;
|
||
|
|
self.defaultYaw = camera:GetYaw();
|
||
|
|
|
||
|
|
camera.panningXOffset = 0 or PANNING_OFFSETS_FULL_CENTRAL[1];
|
||
|
|
camera.panningYOffset = PANNING_OFFSETS_FULL_CENTRAL[2];
|
||
|
|
|
||
|
|
self:SetViewInsets(0, 0, 0, 0);
|
||
|
|
|
||
|
|
|
||
|
|
--Backdrop Reference Points
|
||
|
|
local point1 = self:CreateTexture(nil, "OVERLAY", "NarciModelScene3DPointTemplate");
|
||
|
|
point1:SetColorTexture(0, 0, 1);
|
||
|
|
self.pointFar = point1;
|
||
|
|
|
||
|
|
local point2 = self:CreateTexture(nil, "OVERLAY", "NarciModelScene3DPointTemplate");
|
||
|
|
point2:SetColorTexture(1, 0, 0);
|
||
|
|
self.pointNear = point2;
|
||
|
|
|
||
|
|
local point3 = self:CreateTexture(nil, "OVERLAY", "NarciModelScene3DPointTemplate");
|
||
|
|
point2:SetColorTexture(0, 1, 0);
|
||
|
|
self.point3 = point3;
|
||
|
|
|
||
|
|
--[[
|
||
|
|
point1:Show();
|
||
|
|
point2:Show();
|
||
|
|
point3:Show();
|
||
|
|
--]]
|
||
|
|
|
||
|
|
self.near = - 2.3;
|
||
|
|
self.far = 0;
|
||
|
|
function ChangeFar(x)
|
||
|
|
self.far = x;
|
||
|
|
print("Far: "..x)
|
||
|
|
end
|
||
|
|
function ChangeNear(x)
|
||
|
|
self.near = x;
|
||
|
|
print("Near: "..x)
|
||
|
|
end
|
||
|
|
|
||
|
|
local Backdrop = self.Backdrop;
|
||
|
|
local w, h = self:GetSize();
|
||
|
|
w = 1.1*w
|
||
|
|
Backdrop:ClearAllPoints();
|
||
|
|
Backdrop:SetSize(w, 554/2048* w);
|
||
|
|
Backdrop:SetPoint("CENTER", point1, "CENTER", 0, 0);
|
||
|
|
|
||
|
|
local BackdropBlur = self.BackdropBlur;
|
||
|
|
BackdropBlur:ClearAllPoints();
|
||
|
|
BackdropBlur:ClearAllPoints();
|
||
|
|
BackdropBlur:SetSize(w, 554/2048* w);
|
||
|
|
BackdropBlur:SetPoint("CENTER", point1, "CENTER", 0, 0);
|
||
|
|
|
||
|
|
local Backdrop2 = self.Backdrop2;
|
||
|
|
Backdrop2:ClearAllPoints();
|
||
|
|
Backdrop2:SetSize(w, 877/2048*w);
|
||
|
|
Backdrop2:SetPoint("BOTTOM", Backdrop, "CENTER", 0, 0);
|
||
|
|
|
||
|
|
local Backdrop3 = self.Backdrop3;
|
||
|
|
Backdrop3:ClearAllPoints();
|
||
|
|
Backdrop3:SetSize(w, 877/2048*w);
|
||
|
|
Backdrop3:SetPoint("BOTTOM", Backdrop, "CENTER", 0, 0);
|
||
|
|
|
||
|
|
Backdrop:SetTexture("Interface/AddOns/Narcissus/Art/Modules/Outfit/Backdrop/Ground", nil, nil, "TRILINEAR");
|
||
|
|
BackdropBlur:SetTexture("Interface/AddOns/Narcissus/Art/Modules/Outfit/Backdrop/GroundBlur", nil, nil, "TRILINEAR");
|
||
|
|
Backdrop2:SetTexture("Interface/AddOns/Narcissus/Art/Modules/Outfit/Backdrop/Distance", nil, nil, "TRILINEAR");
|
||
|
|
Backdrop3:SetTexture("Interface/AddOns/Narcissus/Art/Modules/Outfit/Backdrop/DistanceBlur", nil, nil, "TRILINEAR");
|
||
|
|
BackdropBlur:SetAlpha(0);
|
||
|
|
|
||
|
|
--Model Rotation
|
||
|
|
self.lastDeltaX = 0;
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:OnShow()
|
||
|
|
if not self.hasPreloaded then
|
||
|
|
self.hasPreloaded = true;
|
||
|
|
local preload = true;
|
||
|
|
self:GetNarciActor(1, preload);
|
||
|
|
self:GetNarciActor(2, preload);
|
||
|
|
|
||
|
|
local ambient = self:CreateActor();
|
||
|
|
ambient:SetModelByFileID(1688083);
|
||
|
|
ambient:SetScale(0.02);
|
||
|
|
ambient:SetAnimation(0, 0, 1);
|
||
|
|
ambient:SetDesaturation(1);
|
||
|
|
ambient:SetPosition(30, 30, 20);
|
||
|
|
ambient:SetAlpha(0.5);
|
||
|
|
|
||
|
|
--[[
|
||
|
|
local arrow = self:CreateActor();
|
||
|
|
arrow:SetModelByFileID(1346220);
|
||
|
|
arrow:SetScale(0.5);--7228
|
||
|
|
arrow:SetPosition(0, 0, 0);
|
||
|
|
arrow.offsetX, arrow.offsetY, arrow.offsetZ = 1.1, -0.34, 2.78;
|
||
|
|
arrow:SetUseCenterForOrigin(0,0,0);
|
||
|
|
arrow:SetYaw(YAW_FACING_FORWARD);
|
||
|
|
ARROW = arrow
|
||
|
|
self.narciActor[1].arrow = arrow;
|
||
|
|
|
||
|
|
function ArrowPos(x, y, z)
|
||
|
|
if x then
|
||
|
|
arrow.offsetX = x;
|
||
|
|
end
|
||
|
|
if y then
|
||
|
|
arrow.offsetY = y;
|
||
|
|
end
|
||
|
|
if z then
|
||
|
|
arrow.offsetZ = z;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
--]]
|
||
|
|
end
|
||
|
|
self.lastDeltaX = 0;
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:OnUpdate(elapsed)
|
||
|
|
if self.activeCamera then
|
||
|
|
self.activeCamera:OnUpdate(elapsed);
|
||
|
|
end
|
||
|
|
|
||
|
|
local x1, y1 = self:Project3DPointTo2D(0, 0, 0);
|
||
|
|
self.pointFar:SetPoint("CENTER", self, "BOTTOMLEFT", x1, y1);
|
||
|
|
local x2, y2 = self:Project3DPointTo2D(-2.0, -0.43, 0);
|
||
|
|
self.pointNear:SetPoint("CENTER", self, "BOTTOMLEFT", x2, y2);
|
||
|
|
local x3, y3 = self:Project3DPointTo2D(0, 9999, 0);
|
||
|
|
self.point3:SetPoint("CENTER", self, "BOTTOMLEFT", x3, y3);
|
||
|
|
|
||
|
|
if not self.defaultDistance then
|
||
|
|
self.defaultDistance = abs(x2 - x1);
|
||
|
|
self.scaleFactor = 1;
|
||
|
|
else
|
||
|
|
local scale = abs(x1 - x2) / self.defaultDistance / self.scaleFactor;
|
||
|
|
self.Backdrop:SetScale( scale );
|
||
|
|
self.BackdropBlur:SetScale( scale );
|
||
|
|
self.Backdrop2:SetScale( scale );
|
||
|
|
self.Backdrop3:SetScale( scale );
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.handleActorYaw then
|
||
|
|
local deltaX, deltaY = GetScaledCursorDelta();
|
||
|
|
--local x, y = GetCursorPosition();
|
||
|
|
--local scale = UIParent:GetEffectiveScale();
|
||
|
|
--print(x/scale)
|
||
|
|
self.lastDeltaX = deltaX;
|
||
|
|
if deltaX ~= 0 then
|
||
|
|
local facing = self.activeActor:GetYaw() + deltaX * 0.008937;
|
||
|
|
self.activeActor:SetFacing(facing);
|
||
|
|
if self.secondActor then
|
||
|
|
self.secondActor:SetFacing(facing + 3.14);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
elseif self.keyboardMode then
|
||
|
|
local deltaX = self.direction * min(5, abs(self.lastDeltaX) + 20 * elapsed);
|
||
|
|
self.lastDeltaX = deltaX;
|
||
|
|
local facing = self.activeActor:GetYaw() + deltaX * 0.008937;
|
||
|
|
self.activeActor:SetFacing(facing);
|
||
|
|
if self.secondActor then
|
||
|
|
self.secondActor:SetFacing(facing);
|
||
|
|
end
|
||
|
|
elseif self.handleInertia then
|
||
|
|
local lastDeltaX = self.lastDeltaX;
|
||
|
|
if lastDeltaX > 0 then
|
||
|
|
lastDeltaX = max(0, lastDeltaX - 20 * (elapsed) );
|
||
|
|
elseif lastDeltaX < 0 then
|
||
|
|
lastDeltaX = min(0, lastDeltaX + 20 * (elapsed) );
|
||
|
|
else
|
||
|
|
self.handleInertia = false;
|
||
|
|
end
|
||
|
|
local facing = self.activeActor:GetYaw() + lastDeltaX * 0.008937;
|
||
|
|
self.activeActor:SetFacing(facing);
|
||
|
|
if self.secondActor then
|
||
|
|
self.secondActor:SetFacing(facing);
|
||
|
|
end
|
||
|
|
self.lastDeltaX = lastDeltaX;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:OnEnter()
|
||
|
|
--[[
|
||
|
|
local actor = self:GetNarciActor(1);
|
||
|
|
actor:SetAnimation(1330, 0, 1);
|
||
|
|
--]]
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:OnLeave()
|
||
|
|
--[[
|
||
|
|
local actor = self:GetNarciActor(1);
|
||
|
|
actor:SetAnimation(0, 0, 0);
|
||
|
|
--]]
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:OnMouseUp(button)
|
||
|
|
if button == "LeftButton" then
|
||
|
|
self.isLeftButtonDown = false;
|
||
|
|
self.handleActorYaw = false;
|
||
|
|
self.handleInertia = false;
|
||
|
|
self.lastDeltaX = 0;
|
||
|
|
elseif button == "RightButton" then
|
||
|
|
self.isRightButtonDown = false;
|
||
|
|
--[[
|
||
|
|
local camera = self.narciCamera;
|
||
|
|
local modelYaw = self.narciActor[1]:GetYaw();
|
||
|
|
local x, y, z = self:GetCameraPosition()
|
||
|
|
print(modelYaw - (camera:GetYaw() - self.defaultYaw) );
|
||
|
|
print("Panning offsets:", camera.panningXOffset, camera.panningYOffset)
|
||
|
|
print("Zoom:", camera:GetZoomDistance());
|
||
|
|
|
||
|
|
|
||
|
|
--]]
|
||
|
|
self:UpdateTriggerArea();
|
||
|
|
|
||
|
|
local scale = 1 or UIParent:GetEffectiveScale();
|
||
|
|
local xpos = GetCursorPosition() / scale;
|
||
|
|
local left = self:GetLeft() / scale;
|
||
|
|
xpos = xpos - left;
|
||
|
|
print(xpos)
|
||
|
|
for actorIndex, area in pairs(self.triggerAreaSize) do
|
||
|
|
if xpos >= area[1] and xpos <= area[2] then
|
||
|
|
print(actorIndex);
|
||
|
|
return
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.activeCamera then
|
||
|
|
self.activeCamera:OnMouseUp(button);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitModelSceneMixin:OnMouseDown(button)
|
||
|
|
if button == "LeftButton" then
|
||
|
|
--self.isLeftButtonDown = true;
|
||
|
|
if self:GetActiveActor() then
|
||
|
|
self.handleActorYaw = true;
|
||
|
|
end
|
||
|
|
elseif button == "RightButton" then
|
||
|
|
self.isRightButtonDown = true;
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.activeCamera then
|
||
|
|
self.activeCamera:OnMouseUp(button);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
------------------------------------------------------------------
|
||
|
|
NarciOutfitMixin = {};
|
||
|
|
|
||
|
|
function NarciOutfitMixin:SetUIElements()
|
||
|
|
self.Background:SetColorTexture(GRAY_90, GRAY_90, GRAY_90); --GRAY_90
|
||
|
|
self.ModelScene.GreyBackdrop:SetColorTexture(GRAY_90, GRAY_90, GRAY_90);
|
||
|
|
self.SetList.Background:SetColorTexture(GRAY_90, GRAY_90, GRAY_90);
|
||
|
|
|
||
|
|
--Assigning animated objects
|
||
|
|
BlackOverlay = self.BlackOverlay;
|
||
|
|
SetList = self.SetList;
|
||
|
|
SetListScrollChild = SetList.ScrollChild;
|
||
|
|
SetListModel = SetList.ModelContainer;
|
||
|
|
LeftTab = self.LeftTab;
|
||
|
|
|
||
|
|
animShowSetList.object = SetList.Background;
|
||
|
|
animShowSetList.frame = SetList;
|
||
|
|
|
||
|
|
--Assigning Scripts
|
||
|
|
BlackOverlay:SetScript("OnMouseDown", HideSetList);
|
||
|
|
SetList:SetScript("OnMouseDown", SetList_OnMouseDown);
|
||
|
|
|
||
|
|
--Create Navigation Buttons
|
||
|
|
local baseFrameLevel = self:GetFrameLevel();
|
||
|
|
local button;
|
||
|
|
local buttons = {};
|
||
|
|
for i = 1, #navigationStrutcure do
|
||
|
|
button = CreateFrame("Button", nil, self, "Narci_TextNavigationButtonTemplate");
|
||
|
|
tinsert(buttons, button);
|
||
|
|
button:SetFrameLevel(baseFrameLevel + 2);
|
||
|
|
if i == 1 then
|
||
|
|
button:SetPoint("TOPLEFT", self.Inset, "TOPLEFT", 0, 0);
|
||
|
|
button:SetScript("OnClick", function()
|
||
|
|
ShowLeftTab(false);
|
||
|
|
ModelScene:ShowTriggerArea(true);
|
||
|
|
end);
|
||
|
|
else
|
||
|
|
button:SetPoint("LEFT", buttons[i - 1], "RIGHT", 8, 0);
|
||
|
|
end
|
||
|
|
button.level = i;
|
||
|
|
end
|
||
|
|
self.navigationButtons = buttons;
|
||
|
|
self:UpdateNavigationButtons();
|
||
|
|
|
||
|
|
|
||
|
|
--Left Tab
|
||
|
|
CreateLeftTabNavigations(LeftTab);
|
||
|
|
|
||
|
|
--Create Item Buttons
|
||
|
|
ItemModelTab = LeftTab.Create;
|
||
|
|
ItemModelTab:Load();
|
||
|
|
|
||
|
|
--Create Item Source Button
|
||
|
|
ItemListTab = LeftTab.ItemList;
|
||
|
|
ItemListTab:Load();
|
||
|
|
|
||
|
|
animNavigationHighlight.object = LeftTab.Navigation.BackgroundMask;
|
||
|
|
|
||
|
|
--Maximize Button
|
||
|
|
local DEFAULT_WIDTH, DEFAULT_HEIGHT = 855, 481;
|
||
|
|
self:SetSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||
|
|
|
||
|
|
local function Maximize(isMaximized)
|
||
|
|
if isMaximized then
|
||
|
|
local uiScale = UIParent:GetEffectiveScale();
|
||
|
|
width0, height0 = UIParent:GetWidth() * uiScale, UIParent:GetHeight() * uiScale;
|
||
|
|
local newWidth, newHeight, scaleFactor;
|
||
|
|
|
||
|
|
if width0 / height0 >= 16/9 then
|
||
|
|
newHeight = height0;
|
||
|
|
newWidth = height0 * 16/9;
|
||
|
|
scaleFactor = height0 / DEFAULT_HEIGHT;
|
||
|
|
elseif width0 / height0 < 16/9 then
|
||
|
|
newWidth = width0;
|
||
|
|
newHeight = width * 9/16;
|
||
|
|
scaleFactor = width0 / DEFAULT_WIDTH;
|
||
|
|
end
|
||
|
|
self:SetPoint("CENTER", UIParent, "CENTER", 0, 0);
|
||
|
|
self:SetSize(newWidth, newHeight);
|
||
|
|
Narci_ItemCollection:Scale(scaleFactor);
|
||
|
|
local fontPath, fontHeight = NarciOutfitSearchBox:GetFont();
|
||
|
|
if not self.defaultFontHeight then
|
||
|
|
self.defaultFontHeight = fontHeight;
|
||
|
|
end
|
||
|
|
NarciOutfitSearchBox:SetFont(fontPath, self.defaultFontHeight / scaleFactor);
|
||
|
|
self.scaleFactor = scaleFactor;
|
||
|
|
NarciCamera.scaleFactor = scaleFactor;
|
||
|
|
ModelSceneCamera.panningXOffset = ModelSceneCamera.panningXOffset * scaleFactor;
|
||
|
|
ModelSceneCamera.panningYOffset = ModelSceneCamera.panningYOffset * scaleFactor;
|
||
|
|
else
|
||
|
|
self:SetPoint("CENTER", UIParent, "CENTER", 0, 20);
|
||
|
|
self:SetSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||
|
|
Narci_ItemCollection:Scale(1);
|
||
|
|
local fontPath = NarciOutfitSearchBox:GetFont();
|
||
|
|
NarciOutfitSearchBox:SetFont(fontPath, self.defaultFontHeight or 9);
|
||
|
|
NarciCamera.scaleFactor = 1;
|
||
|
|
ModelSceneCamera.panningXOffset = ModelSceneCamera.panningXOffset / self.scaleFactor;
|
||
|
|
ModelSceneCamera.panningYOffset = ModelSceneCamera.panningYOffset / self.scaleFactor;
|
||
|
|
self.scaleFactor = 1;
|
||
|
|
end
|
||
|
|
|
||
|
|
After(0, function()
|
||
|
|
ModelScene:UpdateTriggerArea();
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
self.MaximizeButton.func = Maximize;
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:UpdateNavigationButtons(level)
|
||
|
|
level = level or 1;
|
||
|
|
local button, info;
|
||
|
|
|
||
|
|
for i = 1, NUM_LEVEL do
|
||
|
|
button = self.navigationButtons[i];
|
||
|
|
if i < level then
|
||
|
|
--Update the buttons to the left
|
||
|
|
button.isCurrent = nil;
|
||
|
|
button:ResetTextColor();
|
||
|
|
else
|
||
|
|
info = navigationStrutcure[i];
|
||
|
|
button.scriptType = info.scriptType;
|
||
|
|
if i == level then
|
||
|
|
button.isCurrent = true;
|
||
|
|
button:SetLabel(info.name);
|
||
|
|
button:Show();
|
||
|
|
else
|
||
|
|
button:Hide();
|
||
|
|
button.isCurrent = nil;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:SetStructure(level, name, scriptType)
|
||
|
|
navigationStrutcure[level] = { ["name"] = name, ["scriptType"] = scriptType};
|
||
|
|
self:UpdateNavigationButtons(level);
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:OnLoad()
|
||
|
|
self.commandList = {};
|
||
|
|
OutfitFrame = self;
|
||
|
|
self:SetUIElements();
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:OnClick()
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:GoToCamera(index)
|
||
|
|
NarciCamera:GoToCamera(index);
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:ShowSecondActor(isOutfitComplete)
|
||
|
|
if not isOutfitComplete then
|
||
|
|
Actor2EnterScene();
|
||
|
|
else
|
||
|
|
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:GetActiveTabIndex()
|
||
|
|
return self.activeTabIndex or 0
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:SetActiveTabIndex(index)
|
||
|
|
self.activeTabIndex = index;
|
||
|
|
self.activeCommandList = self.commandList[index] or {};
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:AddCommand(panelIndex, key, func)
|
||
|
|
--panelIndex: 1 Create 2
|
||
|
|
if type(panelIndex) == "number" then
|
||
|
|
panelIndex = {panelIndex};
|
||
|
|
end
|
||
|
|
|
||
|
|
for i = 1, #panelIndex do
|
||
|
|
local index = panelIndex[i];
|
||
|
|
if not self.commandList[index] then
|
||
|
|
self.commandList[index] = {};
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.commandList[index][key] then
|
||
|
|
print("conflict! Panel: #"..index.." Key: "..key);
|
||
|
|
else
|
||
|
|
self.commandList[index][key] = func;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:OnKeyDown(key)
|
||
|
|
if key == "ESCAPE" then
|
||
|
|
if self.MaximizeButton.isMaximized then
|
||
|
|
self:SetPropagateKeyboardInput(false);
|
||
|
|
self.MaximizeButton:Click();
|
||
|
|
else
|
||
|
|
self:SetPropagateKeyboardInput(true);
|
||
|
|
end
|
||
|
|
elseif key == "X" then
|
||
|
|
self.CloseButton:Click();
|
||
|
|
self:SetPropagateKeyboardInput(false);
|
||
|
|
elseif self.activeCommandList and self.activeCommandList[key] then
|
||
|
|
self:SetPropagateKeyboardInput(false);
|
||
|
|
local func = self.activeCommandList[key];
|
||
|
|
func();
|
||
|
|
else
|
||
|
|
self:SetPropagateKeyboardInput(true);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:OnKeyUp(key)
|
||
|
|
if key == "Q" or key == "E" then
|
||
|
|
if self.ModelScene.activeActor then
|
||
|
|
self.ModelScene.keyboardMode = false;
|
||
|
|
self.ModelScene.handleInertia = true;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function NarciOutfitMixin:Open()
|
||
|
|
FadeFrame(self, 0.2, "IN");
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
local function InsertCommandList()
|
||
|
|
local function RotateModel(direction)
|
||
|
|
--direction: ±1
|
||
|
|
ModelScene.keyboardMode = true;
|
||
|
|
ModelScene.direction = direction;
|
||
|
|
end
|
||
|
|
|
||
|
|
OutfitFrame:AddCommand( {1, 2}, "Q", function()
|
||
|
|
RotateModel(-1);
|
||
|
|
end);
|
||
|
|
|
||
|
|
OutfitFrame:AddCommand( {1, 2}, "E", function()
|
||
|
|
RotateModel(1);
|
||
|
|
end);
|
||
|
|
|
||
|
|
local _, _, raceID = UnitRace("player");
|
||
|
|
if raceID == 22 then
|
||
|
|
OutfitFrame:AddCommand(1, "TAB", function()
|
||
|
|
ModelScene:SwitchToAlternateActor();
|
||
|
|
end)
|
||
|
|
|
||
|
|
|
||
|
|
After(2, function()
|
||
|
|
local eventFrame = CreateFrame("Frame");
|
||
|
|
eventFrame:RegisterEvent("UNIT_MODEL_CHANGED");
|
||
|
|
|
||
|
|
eventFrame:SetScript("OnEvent", function(eventFrame, event, ...)
|
||
|
|
print(event)
|
||
|
|
if event == "UNIT_MODEL_CHANGED" then
|
||
|
|
local unit = ...;
|
||
|
|
if unit == "player" then
|
||
|
|
local _, inHumanForm = HasAlternateForm();
|
||
|
|
if inHumanForm ~= ModelScene.inHumanForm then
|
||
|
|
After(0.2, function()
|
||
|
|
ModelScene:SwitchToAlternateActor(inHumanForm);
|
||
|
|
end)
|
||
|
|
eventFrame:UnregisterEvent("UNIT_MODEL_CHANGED");
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
---------------------------------------------------------------
|
||
|
|
local function InitializeCamera()
|
||
|
|
local function InterpolateDimension(lastValue, targetValue, amount, elapsed)
|
||
|
|
return lastValue and amount and DeltaLerp(lastValue, targetValue, amount, elapsed) or targetValue;
|
||
|
|
end
|
||
|
|
|
||
|
|
ModelSceneCamera.total = 0;
|
||
|
|
ModelSceneCamera.customDuration = 1;
|
||
|
|
ModelSceneCamera.interpolatedYaw = pi/2;
|
||
|
|
|
||
|
|
function ModelSceneCamera:UpdateInterpolationTargets(elapsed)
|
||
|
|
local yaw, pitch, roll = self:GetDerivedOrientation();
|
||
|
|
local targetX, targetY, targetZ = self:GetDerivedTarget();
|
||
|
|
local zoomDistance = self:GetDerivedZoomDistance();
|
||
|
|
|
||
|
|
self.interpolatedYaw = InterpolateDimension(self.interpolatedYaw, yaw, self.yawInterpolationAmount, elapsed);
|
||
|
|
self.interpolatedPitch = InterpolateDimension(self.interpolatedPitch, pitch, self.pitchInterpolationAmount, elapsed);
|
||
|
|
self.interpolatedRoll = InterpolateDimension(self.interpolatedRoll, roll, self.rollInterpolationAmount, elapsed);
|
||
|
|
|
||
|
|
if self.updateCamera then
|
||
|
|
self.total = self.total + elapsed;
|
||
|
|
self.interpolatedZoomDistance = inOutSineZero(self.total, self.fromZoomDistance, self.toZoomDistance, self.customDuration);
|
||
|
|
--self.interpolatedYaw = inOutSine(self.total, self.fromYaw, self.toYaw, self.customDuration);
|
||
|
|
--InterpolateDimension(self.interpolatedYaw, yaw, self.yawInterpolationAmount, elapsed);
|
||
|
|
if self.total >= self.customDuration then
|
||
|
|
self.updateCamera = nil;
|
||
|
|
self.total = 0;
|
||
|
|
end
|
||
|
|
else
|
||
|
|
--self.interpolatedYaw = self.toYaw or self.yaw;
|
||
|
|
end
|
||
|
|
self.interpolatedTargetX = InterpolateDimension(self.interpolatedTargetX, targetX, self.targetInterpolationAmount, elapsed);
|
||
|
|
self.interpolatedTargetY = InterpolateDimension(self.interpolatedTargetY, targetY, self.targetInterpolationAmount, elapsed);
|
||
|
|
self.interpolatedTargetZ = InterpolateDimension(self.interpolatedTargetZ, targetZ, self.targetInterpolationAmount, elapsed);
|
||
|
|
end
|
||
|
|
|
||
|
|
function ModelSceneCamera:SetYaw(yaw)
|
||
|
|
self.yaw = yaw;
|
||
|
|
self.toYaw = yaw;
|
||
|
|
end
|
||
|
|
|
||
|
|
function ModelSceneCamera:GetYaw()
|
||
|
|
return self.yaw or self.toYaw
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
local Initialize = CreateFrame("Frame")
|
||
|
|
Initialize:RegisterEvent("PLAYER_ENTERING_WORLD");
|
||
|
|
Initialize:SetScript("OnEvent", function(self, event)
|
||
|
|
self:UnregisterEvent("PLAYER_ENTERING_WORLD");
|
||
|
|
Narci_Outfit.ModelScene:Initialize();
|
||
|
|
SetList_OnLoad(SetList);
|
||
|
|
InitializeCamera();
|
||
|
|
InsertCommandList();
|
||
|
|
end)
|
||
|
|
|
||
|
|
local angleInc = 0.05
|
||
|
|
function myOnUpdate(self, elapsed)
|
||
|
|
--self.timer = self.timer + elapsed;
|
||
|
|
--if ( self.timer > 0.02 ) then
|
||
|
|
self.hAngle = self.hAngle - angleInc;
|
||
|
|
self.s = sin(self.hAngle);
|
||
|
|
self.c = cos(self.hAngle);
|
||
|
|
self.tex:SetTexCoord( 0.5-self.s, 0.5+self.c,
|
||
|
|
0.5+self.c, 0.5+self.s,
|
||
|
|
0.5-self.c, 0.5-self.s,
|
||
|
|
0.5+self.s, 0.5-self.c);
|
||
|
|
--self.timer = 0;
|
||
|
|
--end
|
||
|
|
end
|
||
|
|
|
||
|
|
function RotateTexture(degrees)
|
||
|
|
text = TestTexture;
|
||
|
|
local angle = math.rad(degrees)
|
||
|
|
local cos, sin = math.cos(angle), math.sin(angle)
|
||
|
|
text:SetTexCoord((sin - cos), -(cos + sin), -cos, -sin, sin, -cos, 0, 0)
|
||
|
|
end
|