{"id":"blukezz/snowlib","name":"snowlib","scope":"blukezz","platform":"roblox","description":"Mirrored from the Wally registry.","version":"1.0.0","latest":"1.0.0","versions":["1.0.0"],"license":"LGPL-3.0","licenseRating":"caution","licenseCaveats":["LGPL assumes users can swap out the library. In a bundled Roblox game that boundary is murky — modifying the package creates source obligations, and even unmodified use is legally untested in this context.","License identified from the packaged LICENSE file; the manifest declared none."],"licenseVerified":true,"dependencies":{"arxkdev/beziertween":{"version":"^0.0.3","alias":"beziertween"}},"integrity":"f2d1c5462f7b60350c1d110efab905a56d79edbdaf7e36d776af2afc08c577e4","likes":0,"downloads":0,"install":"forest install blukezz/snowlib","url":"https://forest.dev/p/roblox/blukezz/snowlib","files":"https://api.forest.dev/ai/package/roblox/blukezz/snowlib/files","readme":"> [!NOTE]\n> 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.\n\n# snowlib\n\n![GET FROM](https://img.shields.io/badge/get_from-grey?style=for-the-badge)\n[![LOADSTRING](https://img.shields.io/badge/loadstring-skyblue?style=for-the-badge)](#loadstring)\n[![WALLY](https://img.shields.io/badge/wally-lightblue?style=for-the-badge)](#wally)\n[![MODEL](https://img.shields.io/badge/model-lightcyan?style=for-the-badge)](#model)\n[![RBXM](https://img.shields.io/badge/RBXM-snow?style=for-the-badge)](https://github.com/Blukezz/snowlb/releases/latest)\n⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥⁥⁥⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥ ⁥⁥⁥⁥ ⁥ ⁥ ⁥⁥⁥⁥⁥⁥⁥⁥\n![VERSION](https://img.shields.io/github/v/release/Blukezz/snowlib?style=for-the-badge&color=lightskyblue)\n⁥ ⁥ ⁥ ⁥ ⁥ ⁥⁥⁥⁥\n[![DISCORD](https://img.shields.io/badge/Discord-powderblue.svg?&logo=discord&logoColor=black&style=for-the-badge)](https://discord.gg/Byq78say2g)\n\n\nsnowlib is a flexible CFrame animation library that supports both **classic procedural animations** and **modern-era keyframe animation and its tools**. Under one clean [TweenService](https://create.roblox.com/docs/reference/engine/classes/TweenService) inspired API but with the power of raw math.\n\n## Key Features\n\n- [FABRIK](#FABRIK) (Inverse Kinematics)\n\n- [Additive](#Additive) Animations\n- Animation  [Blending](#Blending)\n- Framerate Independece\n- [Easing](#Weight) Functions\n- [Bezier](#Weight) Functions\n- Framerate Adaptation for Damping Animations\n- \"[Dynamic](#animationnew-at-a-glance)\" Options\n\n## `Animation.new()` At a Glance\n\nMake a new `Animation` object with the `Animation.new()` function!\n\n> [!TIP]\n> 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!\n\n```lua\nfunction Animation.new(\n    Object: Instance,\n    -- required | Any instance that takes CFrame as a property\n    Property: string,\n    -- required | The name of the CFrame property that you want to animate ex: \"CFrame\"\n    Options: {\n\t    To: CFrame | () -> CFrame,\n        -- required | The target CFrame to animating to or a function that returns a CFrame of what to animate to\n\t    From: (CFrame?) | () -> (CFrame?) | (\"Current\" | \"Live\")?,\n        -- optional | The starting CFrane, a function, \n        --   \"Current\" to set it to the Current property value when the function is ran,\n        --   or \"live\" to continuously update it to the current property value each frame, useful for damping\n        -- \"Current\" by default\n\t    Alpha: (number?) | () -> number?,\n        -- optional | The interpolation factor\n        -- by default, it automatically progresses based on the elapsed time and the duration\n        Weight: (number?) | () -> number?,\n        -- optional | Animation weight, the percentage which the animation would be blended/added to existing animations\n        --   use a negative number for additive animations and a positive number for blending animations\n        -- nil by default, sets as a base animation that overrides\n\t    Easing: (number) -> number?,\n        -- optional | The easing function to apply, use snowlib.Easing for presets or snowlib.Bezier for custom ones\n\t    Duration: (number?) | () -> number?\n        -- optional | The time the animation lasts\n        --   if Alpha is used the duration would no long affect the speed of the animation\n        -- by default the animation would last forever\n    }\n)\n```\n\nReturns a new `Animation` object that can be played with `:Play()`, reset with `:Reset()` and/or be paused with `:Stop()`\n\n## Examples\n\nHere's a simple animation that moves `Part` to `0, 10, 0` in 3 seconds (now with easing).\n\n> [!TIP]\n> 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.\n\n```lua\nlocal Part = Instance.new(\"Part\", game.Workspace)\nPart.Anchored = true\n\nlocal Animation = snowlib.Animation\nlocal EasingFuncs = snowlib.Easing\n\nlocal AnimationExample = Animation.new(Part, \"CFrame\", {\n    To = CFrame.new(0, 10, 0),\n    Easing = EasingFuncs.Quad.Out,\n    Duration = 3\n})\n\nAnimationExample:Play()\n```\n\n`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.\n\n```lua\n  while wait() do\n    wing1w.C0 = clerp(wing1w.C0,cf(-1,0.5,2)*angles(math.rad(80),math.rad(90),math.rad(0)),.3)\n    wing2w.C0 = clerp(wing2w.C0,cf(-1,0,2)*angles(math.rad(85),math.rad(90),math.rad(0)),.3)\n    wing3w.C0 = clerp(wing3w.C0,cf(-1,-0.5,2)*angles(math.rad(90),math.rad(90),math.rad(0)),.3)\n  end\n```\n\nSame animation, but with snowlib.\n\n```lua\nAnimation.new(wing1w, \"C0\", { To = cf(1,-0.5,2) * angles(math.rad(90),math.rad(270),math.rad(0)), Alpha = .3, From = \"Live\" }):Play()\nAnimation.new(wing2w, \"C0\", { To = cf(-1,0,2) * angles(math.rad(85),math.rad(90),math.rad(0)), Alpha = .3,  From = \"Live\" }):Play()\nAnimation.new(wing3w, \"C0\", { To = cf(-1,-0.5,2) * angles(math.rad(90),math.rad(90),math.rad(0)), Alpha = .3, From = \"Live\" }):Play()\n```\n\n## Easing\n\n> [!NOTE]\n> See https://easings.net for more information on all of the included easing functions!\n\nEasing 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.\n\nUse `snowlib.Easing` to get the table of easing functions and then index the easing style then the direction to get the easing function.\n\nHere's a quick example.\n\n```lua\nlocal Easing = snowlib.Easing\n\nlocal BackOut = Easing.Back.Out -- A function (number) -> number\n```\n\n## Bezier\n\n> [!NOTE]\n> The bezier functions uses arxkdev's `beziertween` library. (The previous implmentation w was )\n\n> [!TIP]\n> You can use https://cubic-bezier.com/ to graphically make a cubic bezier easing function and copy + paste the numbers!\n\nVia 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. \n\nThe bezier functions in [bezier.lua](./bezier.lua) return a function that takes in a number from 0 - 1 and outputs a number from 0 - 1. Similar to functions in [easings.lua](./easing.lua).\n\nHere's a quick example.\n\n```lua\nlocal Part = Instance.new(\"Part\", game.Workspace)\nPart.Anchored = true\n\nlocal Animation = snowlib.Animation\nlocal CubicBezier = snowlib.Bezier.Cubic\n\nlocal AnimationExample = Animation.new(Part, \"CFrame\", {\n    To = CFrame.new(0, 10, 0),\n    Easing = CubicBezier(0,.69,.65,.56) -- a custom easing function\n    Duration = 3\n})\n\nAnimationExample:Play()\n```\n\n## Weight\n\nBy setting `Animation.Weight` property, it turns it from a base (normal) animation to a delta (additive / blending) animation.\n\nUnlike bases, deltas doesn't override the currently playing animation if it is ran on the same property. Instead, if the value is positive (blending mode), it interpolates (blends) the delta's CFrame with the CFrame of the base animation.\n\nBut if the value is negative (additive mode), it adds the CFrame to the CFrame of the base animation.\n\n> [!IMPORTANT]\n> For both additive and blending animations they use the magnitude / absolute value of the Weight property as the factor to do these operations \n\nYou can make a animation additive / blend by setting the `Animation.Weight` property which can range from `-1 to 1`\n\n## Loadstring\n\nMeant to be run in a executor-like environment.\n\n```\nloadstring(game:HttpGet(\"https://\"))\n```\n\n## Wally\n\nnoting here yet\n\n## Model\n\nnothing here yet\n\n## Credits\n\n`@egomoose` for the [explanation video](https://www.youtube.com/watch?v=UNoX65PRehA) on FABRIK.\n\n`@index_self` for the code in a [devforum comment](https://devforum.roblox.com/t/luau-easing-styles-implementation/2806396/12) which is the code in [easings.lua](./easing.lua) (im lazy :p).\n\n`@roblox` for their [bezier curve guide](https://web.archive.org/web/20221116215320/https://create.roblox.com/docs/mechanics/bezier-curves)! (article was deleted, the link uses the WayBack machine)\n\n`@arxkdex` for the beziertween library (math is hard ;c).\n\n## color pallete\n\n⁥![Version](https://img.shields.io/badge/version-0.3.2-skyblue?style=for-the-badge)\n⁥![Version](https://img.shields.io/badge/version-0.3.2-lightskyblue?style=for-the-badge)\n⁥![Version](https://img.shields.io/badge/version-0.3.2-lightblue?style=for-the-badge)\n⁥![Version](https://img.shields.io/badge/version-0.3.2-powderblue?style=for-the-badge)\n⁥![Version](https://img.shields.io/badge/version-0.3.2-lightcyan?style=for-the-badge)\n⁥![Version](https://img.shields.io/badge/version-0.3.2-snow?style=for-the-badge)","readmeTruncated":false}