Note
Still a work in progress, expect bugs and untested features as this project is getting set up. And as a part of a larger project, it is the main export format of Snow Animator (coming soon) which is not unlike another animation tool, Moon Animator. To make a new workflow option for developers.
snowlib is a flexible CFrame animation library that supports both classic procedural animations and modern-era keyframe animation and its tools. Under one clean TweenService inspired API but with the power of raw math.
-
FABRIK (Inverse Kinematics)
-
Additive Animations
-
Animation Blending
-
Framerate Independece
-
Easing Functions
-
Bezier Functions
-
Framerate Adaptation for Damping Animations
-
"Dynamic" Options
Make a new Animation object with the Animation.new() function!
Tip
Values in the Options table can be functions! (aka a Dynamic Option™) They would be ran every frame and would use what the Dynamic Option returns. Go crazy with it!
function Animation.new(
Object: Instance,
-- required | Any instance that takes CFrame as a property
Property: string,
-- required | The name of the CFrame property that you want to animate ex: "CFrame"
Options: {
To: CFrame | () -> CFrame,
-- required | The target CFrame to animating to or a function that returns a CFrame of what to animate to
From: (CFrame?) | () -> (CFrame?) | ("Current" | "Live")?,
-- optional | The starting CFrane, a function,
-- "Current" to set it to the Current property value when the function is ran,
-- or "live" to continuously update it to the current property value each frame, useful for damping
-- "Current" by default
Alpha: (number?) | () -> number?,
-- optional | The interpolation factor
-- by default, it automatically progresses based on the elapsed time and the duration
Weight: (number?) | () -> number?,
-- optional | Animation weight, the percentage which the animation would be blended/added to existing animations
-- use a negative number for additive animations and a positive number for blending animations
-- nil by default, sets as a base animation that overrides
Easing: (number) -> number?,
-- optional | The easing function to apply, use snowlib.Easing for presets or snowlib.Bezier for custom ones
Duration: (number?) | () -> number?
-- optional | The time the animation lasts
-- if Alpha is used the duration would no long affect the speed of the animation
-- by default the animation would last forever
}
)Returns a new Animation object that can be played with :Play(), reset with :Reset() and/or be paused with :Stop()
Here's a simple animation that moves Part to 0, 10, 0 in 3 seconds (now with easing).
Tip
Don't want to make 1 billion variables for all the animations? You can create a immediately run a animation if you'd like! It'll get garbage collected once it stops playing.
local Part = Instance.new("Part", game.Workspace)
Part.Anchored = true
local Animation = snowlib.Animation
local EasingFuncs = snowlib.Easing
local AnimationExample = Animation.new(Part, "CFrame", {
To = CFrame.new(0, 10, 0),
Easing = EasingFuncs.Quad.Out,
Duration = 3
})
AnimationExample:Play()clerp CFrame animations are pretty ancient, but here's one! They are a sort of a "damping animation" since every frame it moves 0.3 times or 30% closer to the target while using the CFrame from the last frame. Making a "out" easing function-like look.
while wait() do
wing1w.C0 = clerp(wing1w.C0,cf(-1,0.5,2)*angles(math.rad(80),math.rad(90),math.rad(0)),.3)
wing2w.C0 = clerp(wing2w.C0,cf(-1,0,2)*angles(math.rad(85),math.rad(90),math.rad(0)),.3)
wing3w.C0 = clerp(wing3w.C0,cf(-1,-0.5,2)*angles(math.rad(90),math.rad(90),math.rad(0)),.3)
endSame animation, but with snowlib.
Animation.new(wing1w, "C0", { To = cf(1,-0.5,2) * angles(math.rad(90),math.rad(270),math.rad(0)), Alpha = .3, From = "Live" }):Play()
Animation.new(wing2w, "C0", { To = cf(-1,0,2) * angles(math.rad(85),math.rad(90),math.rad(0)), Alpha = .3, From = "Live" }):Play()
Animation.new(wing3w, "C0", { To = cf(-1,-0.5,2) * angles(math.rad(90),math.rad(90),math.rad(0)), Alpha = .3, From = "Live" }):Play()Note
See https://easings.net for more information on all of the included easing functions!
Easing function are a mathematical formula that controls the speed and timing of an animation that come in various styles and directions for example: Quad Out starts fast and ends slower.
Use snowlib.Easing to get the table of easing functions and then index the easing style then the direction to get the easing function.
Here's a quick example.
local Easing = snowlib.Easing
local BackOut = Easing.Back.Out -- A function (number) -> numberVia the Bezier.Quadratic and Bezier.Cubic functions you can create whats essentially custom easing functions defined by a few points that (usually) go from 0 - 1.
Tip
You can use https://cubic-bezier.com/ to graphically make a cubic bezier easing function and copy + paste the numbers!
The Bezier functions in snowlib take in numbers like a conventional cubic-bezier() function but the ones in bezier.lua return functions that take in a number from 0 - 1 and output a number from 0 - 1. Similar to functions in easings.lua.
Here's a quick example.
local Part = Instance.new("Part", game.Workspace)
Part.Anchored = true
local Animation = snowlib.Animation
local CubicBezier = snowlib.Bezier.Cubic
local AnimationExample = Animation.new(Part, "CFrame", {
To = CFrame.new(0, 10, 0),
Easing = CubicBezier(0,.69,.65,.56) -- a custom easing function
Duration = 3
})
AnimationExample:Play()planning on adding info here later
planning on adding info here later
nothign here yet
noting here yet
nothing here yet
@egomoose for the explanation video on FABRIK.
@index_self for the code in a devforum comment which is the code in easings.lua (im lazy :p).
@roblox for their bezier curve guide! (article was deleted, the link uses the WayBack machine)