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.

165 lines
5.2 KiB

3 years ago
local _, addon = ...
local ceil = math.ceil;
local sin = math.sin;
local cos = math.cos;
local acos = math.acos;
local tan = math.tan;
local pi = math.pi;
local UPDATE_THRESHHOLD = 1/1000; --update once when Δprogress > threshhold
local MAX_POLYGON_SIDES = 8; --A polygon will be deemed as a cicle if the number of its sides is larger than this
local function SwipeTrail_PolygonInterection(radius, progress, numSides)
--The intersection point of the polygon and a line (y = x*tanA);
local sector = ceil(progress * numSides);
if sector == 0 then
return 0, radius, 0
else
--print("Sector: "..sector)
local a = 2 * pi / numSides;
local radian1 = a * (sector - 1);
local x1, y1 = radius * sin(radian1), radius * cos(radian1);
--print(x1, y1);
local radian2 = a * sector;
local x2, y2 = radius * sin(radian2), radius * cos(radian2);
--print(x2, y2)
local radian = 2 * pi * progress;
local k;
if x1 == x2 then
local x = x2;
local y = x * acos(radian);
return x, y, radian
else
k = (y1 - y2)/(x1 - x2);
local b = y1 - k * x1;
local c = tan(pi/2 - radian);
local x = b/(c - k);
local y = c * x;
return x, y, radian
end
end
end
local function SwipeTrail_PolygonAlignment(radius, progress, numSides)
--A point moves along the edges of the polygon at a constant speed
local sideProgress = progress * numSides;
local sector = ceil(sideProgress);
if sector == 0 then
return 0, radius, 0
else
local a = 2 * pi / numSides;
local radian1 = a * (sector - 1);
local x1, y1 = radius * sin(radian1), radius * cos(radian1);
local radian2 = a * sector;
local x2, y2 = radius * sin(radian2), radius * cos(radian2);
local sectorProgress = sideProgress - sector + 1; --Won't be zero --(progress - sectorPercentage * (sector - 1))/sectorPercentage
local texRad = a * (sector - 2) + pi/2;
if sectorProgress < 0.1 then
local lastRad = texRad - a/2;
local p = sectorProgress/0.1;
texRad = lastRad * (1 - p) + p * texRad;
elseif sectorProgress > 0.9 then
local nextRad = texRad + a/2;
local p = (0.1 - 1 + sectorProgress)/0.1;
texRad = nextRad * p + (1 - p) * texRad;
end
return x2*sectorProgress + x1*(1 - sectorProgress), y2*sectorProgress + y1*(1 - sectorProgress), texRad --(2 * pi * progress)
end
end
local function SwipeTrail_Circle(radius, progress)
--The basic circular trail
local radian = 2 * pi * progress;
return radius * sin(radian), radius * cos(radian), radian
end
3 years ago
local SwipeTrailFunctions = {};
addon.SwipeTrailFunctions = SwipeTrailFunctions;
SwipeTrailFunctions.Polygon = SwipeTrail_PolygonAlignment;
SwipeTrailFunctions.Circle = SwipeTrail_Circle;
local function ClockFrame_OnUpdate(f, elapsed)
f.t = f.t + elapsed;
if f.t >= f.duration then
f.percentage = 1;
f:Finish();
else
f.percentage = f.t / f.duration;
if f.percentage < 0 then
f.percentage = 0;
end
end
if (f.percentage - f.lastProgress) >= UPDATE_THRESHHOLD then
local x, y, radian = f.positionFunc(f.radius, f.percentage, f.numSides);
f.Pointer:SetPoint("CENTER", f, "CENTER", x, y);
f.Pointer:SetRotation(-radian);
f.lastProgress = f.percentage;
end
end
NarciClockFrameMixin = {};
function NarciClockFrameMixin:SetSwipeRadius(radius)
radius = radius or self.swipeRadius or self:GetHeight()/2;
self.radius = radius;
end
function NarciClockFrameMixin:SetSwipeTrail(numSides)
numSides = numSides or self.numPolygonSides or 0;
if numSides > MAX_POLYGON_SIDES then
numSides = 0;
self.positionFunc = SwipeTrail_Circle;
elseif numSides >= 3 then
self.positionFunc = SwipeTrail_PolygonAlignment;
else
self.positionFunc = SwipeTrail_Circle;
end
self.numSides = numSides;
end
function NarciClockFrameMixin:Init(radius, numSides)
self:SetSwipeRadius(radius);
self:SetSwipeTrail(numSides);
end
function NarciClockFrameMixin:Start(fullDuration, startTime)
self:Show();
self.lastProgress = -1;
self.Pointer:ClearAllPoints();
self.duration = fullDuration;
if not startTime then
startTime = 0;
elseif startTime > fullDuration then
startTime = fullDuration;
end
self.t = startTime;
self:SetScript("OnUpdate", ClockFrame_OnUpdate);
end
function NarciClockFrameMixin:Stop()
self:SetScript("OnUpdate", nil);
self:Hide();
end
function NarciClockFrameMixin:Finish()
self:Stop();
if self.onFinishedFunc then
self.onFinishedFunc(self);
end
end
function NarciClockFrameMixin:OnHide()
if not self.keepOnHide then
self:Stop();
end
end
function NarciClockFrameMixin:SetPointerTexture(texFile)
self.Pointer:SetTexture(texFile, nil, nil, "LINEAR");
end