242 lines
6.8 KiB
Lua
242 lines
6.8 KiB
Lua
-- Animation Stress Profile
|
|
-- Tests animation system with many concurrent animations
|
|
|
|
local FlexLove = require("FlexLove")
|
|
|
|
local profile = {
|
|
animationCount = 100,
|
|
maxAnimations = 1000,
|
|
minAnimations = 10,
|
|
root = nil,
|
|
animations = {},
|
|
elements = {},
|
|
easingFunctions = {
|
|
"linear",
|
|
"easeInQuad",
|
|
"easeOutQuad",
|
|
"easeInOutQuad",
|
|
"easeInCubic",
|
|
"easeOutCubic",
|
|
"easeInOutCubic",
|
|
},
|
|
}
|
|
|
|
function profile.init()
|
|
FlexLove.init({
|
|
width = love.graphics.getWidth(),
|
|
height = love.graphics.getHeight(),
|
|
})
|
|
|
|
profile.buildLayout()
|
|
end
|
|
|
|
function profile.buildLayout()
|
|
profile.root = FlexLove.new({
|
|
width = "100%",
|
|
height = "100%",
|
|
backgroundColor = FlexLove.Color.new(0.05, 0.05, 0.1, 1),
|
|
positioning = "flex",
|
|
flexDirection = "vertical",
|
|
overflowY = "scroll",
|
|
padding = { horizontal = 20, vertical = 20 },
|
|
gap = 10,
|
|
})
|
|
|
|
-- Create animated elements container
|
|
local animationContainer = FlexLove.new({
|
|
width = "100%",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
flexWrap = "wrap",
|
|
gap = 10,
|
|
marginBottom = 20,
|
|
})
|
|
|
|
profile.animations = {}
|
|
profile.elements = {}
|
|
|
|
for i = 1, profile.animationCount do
|
|
local hue = (i / profile.animationCount) * 360
|
|
local baseColor = FlexLove.Color.new(
|
|
0.3 + 0.5 * math.sin(hue * math.pi / 180),
|
|
0.3 + 0.5 * math.sin((hue + 120) * math.pi / 180),
|
|
0.3 + 0.5 * math.sin((hue + 240) * math.pi / 180),
|
|
1
|
|
)
|
|
|
|
-- Choose random easing function
|
|
local easingFunc = profile.easingFunctions[math.random(#profile.easingFunctions)]
|
|
|
|
local box = FlexLove.new({
|
|
width = 60,
|
|
height = 60,
|
|
backgroundColor = baseColor,
|
|
borderRadius = 8,
|
|
margin = { horizontal = 5, vertical = 5 },
|
|
})
|
|
|
|
-- Store base values for animation
|
|
box._baseY = box.y
|
|
box._baseOpacity = 1
|
|
box._baseBorderRadius = 8
|
|
box._baseColor = baseColor
|
|
|
|
-- Create animations manually since elements may not support automatic animation
|
|
local animDuration = 1 + math.random() * 2 -- 1-3 seconds
|
|
|
|
-- Y position animation
|
|
local yAnim = FlexLove.Animation.new({
|
|
duration = animDuration,
|
|
start = { offset = 0 },
|
|
final = { offset = 20 + math.random() * 40 },
|
|
easing = easingFunc,
|
|
}):yoyo(true):repeatCount(0) -- 0 = infinite loop
|
|
|
|
-- Opacity animation
|
|
local opacityAnim = FlexLove.Animation.new({
|
|
duration = animDuration * 0.8,
|
|
start = { opacity = 1 },
|
|
final = { opacity = 0.3 },
|
|
easing = easingFunc,
|
|
}):yoyo(true):repeatCount(0)
|
|
|
|
-- Border radius animation
|
|
local radiusAnim = FlexLove.Animation.new({
|
|
duration = animDuration * 1.2,
|
|
start = { borderRadius = 8 },
|
|
final = { borderRadius = 30 },
|
|
easing = easingFunc,
|
|
}):yoyo(true):repeatCount(0)
|
|
|
|
-- Store animations with element reference
|
|
table.insert(profile.animations, { element = box, animation = yAnim, property = "y" })
|
|
table.insert(profile.animations, { element = box, animation = opacityAnim, property = "opacity" })
|
|
table.insert(profile.animations, { element = box, animation = radiusAnim, property = "borderRadius" })
|
|
|
|
table.insert(profile.elements, box)
|
|
animationContainer:addChild(box)
|
|
end
|
|
|
|
profile.root:addChild(animationContainer)
|
|
|
|
-- Info panel
|
|
local infoPanel = FlexLove.new({
|
|
width = "100%",
|
|
padding = { horizontal = 15, vertical = 15 },
|
|
backgroundColor = FlexLove.Color.new(0.1, 0.1, 0.2, 0.9),
|
|
borderRadius = 8,
|
|
positioning = "flex",
|
|
flexDirection = "vertical",
|
|
gap = 5,
|
|
})
|
|
|
|
infoPanel:addChild(FlexLove.new({
|
|
text = string.format("Animated Elements: %d (Press +/- to adjust)", profile.animationCount),
|
|
fontSize = 18,
|
|
textColor = FlexLove.Color.new(1, 1, 1, 1),
|
|
}))
|
|
|
|
infoPanel:addChild(FlexLove.new({
|
|
text = string.format("Active Animations: %d", #profile.animations),
|
|
fontSize = 14,
|
|
textColor = FlexLove.Color.new(0.8, 0.8, 0.8, 1),
|
|
}))
|
|
|
|
infoPanel:addChild(FlexLove.new({
|
|
text = "Animating: position, opacity, borderRadius",
|
|
fontSize = 14,
|
|
textColor = FlexLove.Color.new(0.8, 0.8, 0.8, 1),
|
|
}))
|
|
|
|
infoPanel:addChild(FlexLove.new({
|
|
text = string.format("Easing Functions: %d variations", #profile.easingFunctions),
|
|
fontSize = 14,
|
|
textColor = FlexLove.Color.new(0.8, 0.8, 0.8, 1),
|
|
}))
|
|
|
|
profile.root:addChild(infoPanel)
|
|
end
|
|
|
|
function profile.update(dt)
|
|
-- Update all animations and apply to elements
|
|
for _, animData in ipairs(profile.animations) do
|
|
animData.animation:update(dt)
|
|
local values = animData.animation:interpolate()
|
|
|
|
if animData.property == "y" and values.offset then
|
|
animData.element.y = (animData.element._baseY or animData.element.y) + values.offset
|
|
elseif animData.property == "opacity" and values.opacity then
|
|
animData.element.opacity = values.opacity
|
|
elseif animData.property == "borderRadius" and values.borderRadius then
|
|
animData.element.borderRadius = values.borderRadius
|
|
end
|
|
end
|
|
end
|
|
|
|
function profile.draw()
|
|
if profile.root then
|
|
profile.root:draw()
|
|
end
|
|
|
|
-- Overlay info
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
love.graphics.print("Animation Stress Test", 10, love.graphics.getHeight() - 100)
|
|
love.graphics.print(
|
|
string.format("Animations: %d | Range: %d-%d",
|
|
#profile.animations,
|
|
profile.minAnimations * 3,
|
|
profile.maxAnimations * 3
|
|
),
|
|
10,
|
|
love.graphics.getHeight() - 80
|
|
)
|
|
love.graphics.print("Press + to add 10 animated elements", 10, love.graphics.getHeight() - 60)
|
|
love.graphics.print("Press - to remove 10 animated elements", 10, love.graphics.getHeight() - 45)
|
|
end
|
|
|
|
function profile.keypressed(key, profiler)
|
|
if key == "=" or key == "+" then
|
|
-- Create snapshot before changing animation count
|
|
if profiler then
|
|
local label = string.format("%d animations", profile.animationCount)
|
|
profiler:createSnapshot(label, {
|
|
animationCount = profile.animationCount,
|
|
activeAnimations = #profile.animations
|
|
})
|
|
end
|
|
|
|
profile.animationCount = math.min(profile.maxAnimations, profile.animationCount + 10)
|
|
profile.buildLayout()
|
|
elseif key == "-" or key == "_" then
|
|
-- Create snapshot before changing animation count
|
|
if profiler then
|
|
local label = string.format("%d animations", profile.animationCount)
|
|
profiler:createSnapshot(label, {
|
|
animationCount = profile.animationCount,
|
|
activeAnimations = #profile.animations
|
|
})
|
|
end
|
|
|
|
profile.animationCount = math.max(profile.minAnimations, profile.animationCount - 10)
|
|
profile.buildLayout()
|
|
end
|
|
end
|
|
|
|
function profile.resize(w, h)
|
|
FlexLove.resize(w, h)
|
|
profile.buildLayout()
|
|
end
|
|
|
|
function profile.reset()
|
|
profile.animationCount = 100
|
|
profile.buildLayout()
|
|
end
|
|
|
|
function profile.cleanup()
|
|
profile.animations = {}
|
|
profile.elements = {}
|
|
profile.root = nil
|
|
end
|
|
|
|
return profile
|