Files
coa-weakauras/WeakAuras/RegionTypes/StopMotion.lua
T
2025-01-06 12:53:01 +01:00

491 lines
17 KiB
Lua

if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end
local AddonName, Private = ...
local texture_types = WeakAuras.StopMotion.texture_types;
local texture_data = WeakAuras.StopMotion.texture_data;
local animation_types = WeakAuras.StopMotion.animation_types;
local L = WeakAuras.L;
local default = {
foregroundTexture = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\StopMotion",
backgroundTexture = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\StopMotion",
desaturateBackground = false,
desaturateForeground = false,
sameTexture = true,
width = 128,
height = 128,
foregroundColor = {1, 1, 1, 1},
backgroundColor = {0.5, 0.5, 0.5, 0.5},
blendMode = "BLEND",
rotation = 0,
discrete_rotation = 0,
mirror = false,
rotate = true,
selfPoint = "CENTER",
anchorPoint = "CENTER",
anchorFrameType = "SCREEN",
xOffset = 0,
yOffset = 0,
frameStrata = 1,
startPercent = 0,
endPercent = 1,
backgroundPercent = 1,
frameRate = 15,
animationType = "loop",
inverse = false,
customForegroundFrames = 0,
customForegroundRows = 16,
customForegroundColumns = 16,
customBackgroundFrames = 0,
customForegroundFileWidth = 0,
customForegroundFileHeight = 0,
customForegroundFrameWidth = 0,
customForegroundFrameHeight = 0,
customBackgroundRows = 16,
customBackgroundColumns = 16,
hideBackground = true
};
local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20;
local properties = {
desaturateForeground = {
display = L["Desaturate Foreground"],
setter = "SetForegroundDesaturated",
type = "bool",
},
desaturateBackground = {
display = L["Desaturate Background"],
setter = "SetBackgroundDesaturated",
type = "bool",
},
foregroundColor = {
display = L["Foreground Color"],
setter = "Color",
type = "color"
},
backgroundColor = {
display = L["Background Color"],
setter = "SetBackgroundColor",
type = "color"
},
width = {
display = L["Width"],
setter = "SetRegionWidth",
type = "number",
min = 1,
softMax = screenWidth,
bigStep = 1,
},
height = {
display = L["Height"],
setter = "SetRegionHeight",
type = "number",
min = 1,
softMax = screenHeight,
bigStep = 1
},
}
WeakAuras.regionPrototype.AddProperties(properties, default);
local function create(parent)
local frame = CreateFrame("Frame", nil, UIParent);
frame.regionType = "stopmotion"
frame:SetMovable(true);
frame:SetResizable(true);
frame:SetMinResize(1, 1);
local background = frame:CreateTexture(nil, "BACKGROUND");
frame.background = background;
background:SetAllPoints(frame);
local foreground = frame:CreateTexture(nil, "ART");
frame.foreground = foreground;
foreground:SetAllPoints(frame);
WeakAuras.regionPrototype.create(frame);
return frame;
end
local function SetTextureViaAtlas(self, texture)
self:SetTexture(texture);
end
local function setTile(texture, frame, rows, columns, frameScaleW, frameScaleH)
frame = frame - 1;
local row = floor(frame / columns);
local column = frame % columns;
local deltaX = frameScaleW / columns
local deltaY = frameScaleH / rows
local left = deltaX * column;
local right = left + deltaX;
local top = deltaY * row;
local bottom = top + deltaY;
pcall(function() texture:SetTexCoord(left, right, top, bottom) end)
end
WeakAuras.setTile = setTile;
local function SetFrameViaAtlas(self, texture, frame)
local frameScaleW = 1
local frameScaleH = 1
if self.fileWidth and self.frameWidth and self.fileWidth > 0 and self.frameWidth > 0 then
frameScaleW = (self.frameWidth * self.columns) / self.fileWidth
end
if self.fileHeight and self.frameHeight and self.fileHeight > 0 and self.frameHeight > 0 then
frameScaleH = (self.frameHeight * self.rows) / self.fileHeight
end
setTile(self, frame, self.rows, self.columns, frameScaleW, frameScaleH);
end
local function SetTextureViaFrames(self, texture)
self:SetTexture(texture .. format("%03d", 0));
self:SetTexCoord(0, 1, 0, 1);
end
local function SetFrameViaFrames(self, texture, frame)
self:SetTexture(texture .. format("%03d", frame));
end
local function modify(parent, region, data)
WeakAuras.regionPrototype.modify(parent, region, data);
region.foreground = region.foreground or {}
region.background = region.background or {}
local pattern = "%.x(%d+)y(%d+)f(%d+)%.[tb][gl][ap]"
local pattern2 = "%.x(%d+)y(%d+)f(%d+)w(%d+)h(%d+)W(%d+)H(%d+)%.[tb][gl][ap]"
do
local tdata = texture_data[data.foregroundTexture];
if (tdata) then
local lastFrame = tdata.count - 1;
region.foreground.lastFrame = lastFrame
region.startFrame = floor( (data.startPercent or 0) * lastFrame) + 1;
region.endFrame = floor( (data.endPercent or 1) * lastFrame) + 1;
region.foreground.rows = tdata.rows;
region.foreground.columns = tdata.columns;
region.foreground.fileWidth = 0
region.foreground.fileHeight = 0
region.foreground.frameWidth = 0
region.foreground.frameHeight = 0
else
local rows, columns, frames = data.foregroundTexture:lower():match(pattern)
if rows then
local lastFrame = tonumber(frames) - 1;
region.foreground.lastFrame = lastFrame
region.startFrame = floor( (data.startPercent or 0) * lastFrame) + 1;
region.endFrame = floor( (data.endPercent or 1) * lastFrame) + 1;
region.foreground.rows = tonumber(rows)
region.foreground.columns = tonumber(columns)
region.foreground.fileWidth = 0
region.foreground.fileHeight = 0
region.foreground.frameWidth = 0
region.foreground.frameHeight = 0
else
local rows, columns, frames, frameWidth, frameHeight, fileWidth, fileHeight = data.foregroundTexture:match(pattern2)
if rows then
local lastFrame = tonumber(frames) - 1;
region.foreground.lastFrame = lastFrame
region.startFrame = floor( (data.startPercent or 0) * lastFrame) + 1;
region.endFrame = floor( (data.endPercent or 1) * lastFrame) + 1;
region.foreground.rows = tonumber(rows)
region.foreground.columns = tonumber(columns)
region.foreground.fileWidth = tonumber(fileWidth)
region.foreground.fileHeight = tonumber(fileHeight)
region.foreground.frameWidth = tonumber(frameWidth)
region.foreground.frameHeight = tonumber(frameHeight)
else
local lastFrame = (data.customForegroundFrames or 256) - 1;
region.foreground.lastFrame = lastFrame
region.startFrame = floor( (data.startPercent or 0) * lastFrame) + 1;
region.endFrame = floor( (data.endPercent or 1) * lastFrame) + 1;
region.foreground.rows = data.customForegroundRows;
region.foreground.columns = data.customForegroundColumns;
region.foreground.fileWidth = data.customForegroundFileWidth
region.foreground.fileHeight = data.customForegroundFileHeight
region.foreground.frameWidth = data.customForegroundFrameWidth
region.foreground.frameHeight = data.customForegroundFrameHeight
end
end
end
end
local backgroundTexture = data.sameTexture
and data.foregroundTexture
or data.backgroundTexture;
do
if data.sameTexture then
region.backgroundFrame = floor( (data.backgroundPercent or 1) * region.foreground.lastFrame + 1);
region.background.rows = region.foreground.rows
region.background.columns = region.foreground.columns
region.background.fileWidth = region.foreground.fileWidth
region.background.fileHeight = region.foreground.fileHeight
region.background.frameWidth = region.foreground.frameWidth
region.background.frameHeight = region.foreground.frameHeight
else
local tdata = texture_data[data.backgroundTexture];
if (tdata) then
local lastFrame = tdata.count - 1;
region.backgroundFrame = floor( (data.backgroundPercent or 1) * lastFrame + 1);
region.background.rows = tdata.rows;
region.background.columns = tdata.columns;
region.background.fileWidth = 0
region.background.fileHeight = 0
region.background.frameWidth = 0
region.background.frameHeight = 0
else
local rows, columns, frames = data.backgroundTexture:lower():match(pattern)
if rows then
local lastFrame = frames - 1;
region.backgroundFrame = floor( (data.backgroundPercent or 1) * lastFrame + 1);
region.background.rows = tonumber(rows)
region.background.columns = tonumber(columns)
region.background.fileWidth = 0
region.background.fileHeight = 0
region.background.frameWidth = 0
region.background.frameHeight = 0
else
local rows, columns, frames, frameWidth, frameHeight, fileWidth, fileHeight = data.backgroundTexture:match(pattern2)
if rows then
local lastFrame = frames - 1;
region.backgroundFrame = floor( (data.backgroundPercent or 1) * lastFrame + 1);
region.background.rows = tonumber(rows)
region.background.columns = tonumber(columns)
region.background.fileWidth = tonumber(fileWidth)
region.background.fileHeight = tonumber(fileHeight)
region.background.frameWidth = tonumber(frameWidth)
region.background.frameHeight = tonumber(frameHeight)
else
local lastFrame = (data.customBackgroundFrames or 256) - 1;
region.backgroundFrame = floor( (data.backgroundPercent or 1) * lastFrame + 1);
region.background.rows = data.customBackgroundRows;
region.background.columns = data.customBackgroundColumns;
region.background.fileWidth = data.customBackgroundFileWidth
region.background.fileHeight = data.customBackgroundFileHeight
region.background.frameWidth = data.customBackgroundFrameWidth
region.background.frameHeight = data.customBackgroundFrameHeight
end
end
end
end
end
if (region.foreground.rows and region.foreground.columns) then
region.foreground.SetBaseTexture = SetTextureViaAtlas;
region.foreground.SetFrame = SetFrameViaAtlas;
else
region.foreground.SetBaseTexture = SetTextureViaFrames;
region.foreground.SetFrame = SetFrameViaFrames;
end
if (region.background.rows and region.background.columns) then
region.background.SetBaseTexture = SetTextureViaAtlas;
region.background.SetFrame = SetFrameViaAtlas;
else
region.background.SetBaseTexture = SetTextureViaFrames;
region.background.SetFrame = SetFrameViaFrames;
end
region.background:SetBaseTexture(backgroundTexture);
region.background:SetFrame(backgroundTexture, region.backgroundFrame or 1);
region.background:SetDesaturated(data.desaturateBackground)
region.background:SetVertexColor(data.backgroundColor[1], data.backgroundColor[2], data.backgroundColor[3], data.backgroundColor[4]);
region.background:SetBlendMode(data.blendMode);
if (data.hideBackground) then
region.background:Hide();
else
region.background:Show();
end
region.foreground:SetBaseTexture(data.foregroundTexture);
region.foreground:SetFrame(data.foregroundTexture, 1);
region.foreground:SetDesaturated(data.desaturateForeground);
region.foreground:SetBlendMode(data.blendMode);
region:SetWidth(data.width);
region:SetHeight(data.height);
region.width = data.width;
region.height = data.height;
region.scalex = 1;
region.scaley = 1;
function region:Scale(scalex, scaley)
region.scalex = scalex;
region.scaley = scaley;
if(scalex < 0) then
region.mirror_h = true;
scalex = scalex * -1;
else
region.mirror_h = nil;
end
region:SetWidth(region.width * scalex);
if(scaley < 0) then
scaley = scaley * -1;
region.mirror_v = true;
else
region.mirror_v = nil;
end
region:SetHeight(region.height * scaley);
end
function region:Color(r, g, b, a)
region.color_r = r;
region.color_g = g;
region.color_b = b;
region.color_a = a;
if (r or g or b) then
a = a or 1;
end
region.foreground:SetVertexColor(region.color_anim_r or r, region.color_anim_g or g, region.color_anim_b or b, region.color_anim_a or a);
end
function region:ColorAnim(r, g, b, a)
region.color_anim_r = r;
region.color_anim_g = g;
region.color_anim_b = b;
region.color_anim_a = a;
if (r or g or b) then
a = a or 1;
end
region.foreground:SetVertexColor(r or region.color_r, g or region.color_g, b or region.color_b, a or region.color_a);
end
function region:GetColor()
return region.color_r or data.color[1], region.color_g or data.color[2],
region.color_b or data.color[3], region.color_a or data.color[4];
end
region:Color(data.foregroundColor[1], data.foregroundColor[2], data.foregroundColor[3], data.foregroundColor[4]);
function region:PreShow()
region.startTime = GetTime();
end
local function onUpdate()
if (not region.startTime) then return end
Private.StartProfileAura(region.id);
Private.StartProfileSystem("stopmotion")
local timeSinceStart = (GetTime() - region.startTime);
local newCurrentFrame = floor(timeSinceStart * (data.frameRate or 15));
if (newCurrentFrame == region.currentFrame) then
Private.StopProfileAura(region.id);
Private.StopProfileSystem("stopmotion")
return;
end
region.currentFrame = newCurrentFrame;
local frames;
local startFrame = region.startFrame;
local endFrame = region.endFrame;
local inverse = data.inverse;
if (endFrame >= startFrame) then
frames = endFrame - startFrame + 1;
else
frames = startFrame - endFrame + 1;
startFrame, endFrame = endFrame, startFrame;
inverse = not inverse;
end
local frame = 0;
if (data.animationType == "loop") then
frame = (newCurrentFrame % frames) + startFrame;
elseif (data.animationType == "bounce") then
local direction = floor(newCurrentFrame / frames) % 2;
if (direction == 0) then
frame = (newCurrentFrame % frames) + startFrame;
else
frame = endFrame - (newCurrentFrame % frames);
end
elseif (data.animationType == "once") then
frame = newCurrentFrame + startFrame
if (frame > endFrame) then
frame = endFrame;
end
elseif (data.animationType == "progress") then
if (not region.state) then
-- Do nothing
elseif (region.state.progressType == "static") then
local value = region.state.value or 0
local total = region.state.total ~= 0 and region.state.total or 1
frame = floor((frames - 1) * value / total) + startFrame;
else
local remaining
if region.state.paused then
remaining = region.state.remaining or 0;
else
remaining = region.state.expirationTime and (region.state.expirationTime - GetTime()) or 0;
end
local progress = region.state.duration and region.state.duration > 0 and (1 - (remaining / region.state.duration)) or 0;
frame = floor( (frames - 1) * progress) + startFrame;
end
end
if (inverse) then
frame = endFrame - frame + startFrame;
end
if (frame > endFrame) then
frame = endFrame
end
if (frame < startFrame) then
frame = startFrame
end
region.foreground:SetFrame(data.foregroundTexture, frame);
Private.StopProfileAura(region.id);
Private.StopProfileSystem("stopmotion")
end;
region.FrameTick = onUpdate;
function region:Update()
if region.state.paused then
if not region.paused then
region:Pause()
end
else
if region.paused then
region:Resume()
end
end
onUpdate();
end
function region:SetForegroundDesaturated(b)
region.foreground:SetDesaturated(b);
end
function region:SetBackgroundDesaturated(b)
region.background:SetDesaturated(b);
end
function region:SetBackgroundColor(r, g, b, a)
region.background:SetVertexColor(r, g, b, a);
end
function region:SetRegionWidth(width)
region.width = width;
region:Scale(region.scalex, region.scaley);
end
function region:SetRegionHeight(height)
region.height = height;
region:Scale(region.scalex, region.scaley);
end
end
local function validate(data)
Private.EnforceSubregionExists(data, "subbackground")
end
WeakAuras.RegisterRegionType("stopmotion", create, modify, default, properties, validate);