Godot: run sequential and parallel animations with less code

Anima

Anima is an addon for Godot that allows you to create sequential and parallel animations with less code compared to Tween.

Introduction

Anima

Creating sequential and parallel animations using Tween can be a bit tedious, and Anima allows you doing that with few lines of code and a simple syntax. It has built-in about 89 animations and 33 easings, with the ability to easily add your own. You can also add your own with a CSS inspired syntax.

Table of Contents

  • Installation
  • Documentation & Demo
  • Differences between Anima and Godot Tween
  • Stay in Touch
  • Contribution
  • License

Installation

This is a regular editor plugin. Copy the contents of addons/Anima into the same folder in your project, and activate it in your project settings.

Documentation & Demo

Check out documentation, demo code and live examples.

Differences between Anima and Godot Tween

Anima Tween
Chaining support for sequential, parallel and concurrent animations possible but need to be done manually
Easing 33 built-in, (it will be extended in 0.2) 10 and no support for custom ones
Create and reuse custom animations 89 built-in, more can be added programmatically possible but not as easy
Animate elements in group yes (it will be extended in 0.2) possible but need to manually animate each individual element
Loop Infinite, Times, and delayed loops Infinite only
Animate relative values yes possible but need to be done manually
Play/Loop backwards yes no
Change speed on fly 0.4 no
Animation path (position only) 0.5 no

What does it mean in terms of code? Here an overview of Anima vs Godot Tween code for simple animation:

Anima vs Godot

For more info about the differences have a look here

Stay in Touch

Contribution

Contributions are welcome and are accepted via pull requests.

License

MIT

Copyright (c) 2021-present, Alessandro Senese (ceceppa)

Owner
Comments
  • Error when trying to play an animation

    Error when trying to play an animation

    I'm not sure if thats intentional but the pivot is passed as a string there and the function expects a dictionary: image image image

    The code that invoked the error:

    var anima := Anima.begin(self)
    anima.then({node = self, animation = "tada", duration = 0.7})
    anima.play()
    

    The object (self) is a MarginContainer if that helps.

  • Initial values do not reset when using an animation repeatedly

    Initial values do not reset when using an animation repeatedly

    Hello, it seems that if you interrupt a currently playing animation with another play() call, it seems to use the current values as the new initial value, and then animate from there, instead of resetting first, and then playing the animation.

    I could be missing a step though; I'm just following what I saw in the docs:

    if Input.is_action_just_pressed("use_ability"):
      var anima = Anima.begin(self)
      anima.then({ node = self, animation = "wobble", duration = 0.2 })
      anima.play()
    

    The animation basically plays everytime I hit a key. Attached is a video of what it looks like. As you can see, it starts to veer way off its original position.

    https://user-images.githubusercontent.com/45138063/153941734-7b249a69-903e-441e-8ccb-134a71d31c3d.mp4

    I checked the live demo for anima and it doesn't seem to have this problem. On checking the code, you seem to avoid this by duplicating the original node then hiding it. That seem like a janky solution for me though.

    My current workaround is to toggle the control's visibility off then on. This only works for nodes in a container though, since the container can reset its children's position/rotation/scale. Still, I was wondering if there's something I'm missing so I don't have to even resort to a workaround?

    Note: I'm using Anima 0.3.1

  • Resetting should_loop variable

    Resetting should_loop variable

    The _should_loop property never gets set to false after calling loop(), which causes the next animations to incorrectly keep looping, even when you only call the play() function.

    I've created a new function clear_loop() that manually sets this variable to false, but I don't think this is the best approach. Maybe we could discuss a better solution in this PR?

  • Visual node editor isn't shown

    Visual node editor isn't shown

    Anima visual node editor remains hidden after clicking on AnimaVisualNode in the scene tree

    Error log:

     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     res://addons/anima/utils/anima_declaration_group.gd:56 - Invalid get index 'property' (on base: 'Dictionary').
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     res://addons/anima/utils/anima_declaration_group.gd:56 - Invalid get index 'property' (on base: 'Dictionary').
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: opacity
     animation not found: opacity
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
     modules/gdscript/gdscript_functions.cpp:788 - passing a Dictionary has been deprecated. Please use Anima.Node / Anima.Group / Anima.Grid instead
     No animation found with name: scale
     animation not found: scale
    
    

    EDIT:

    The errors are at utils/anima_declaration_grid.gd, utils/anima_declaration_group.gd, and utils/anima_declaration_node.gd: at function anima_property It should be .anima_property(property_name) instead of .anima_animation(property_name)

  • Update anima.gd

    Update anima.gd

    In your documentation example you seem to be using type inference:

    var anima := Anima.begin(self)
    
    anima.then({ node = $node, animation = "tada", duration = 0.7 })
    anima.play()
    

    But in your code you are not telling the compiler what type it returns which leads to the following error: image

    The following pull request should fix that. Otherwise you can just change your documentation to not use type inference

  • Cyclic dependecy on editor?

    Cyclic dependecy on editor?

    Anima plugin works well inside the game. But some features to code with anima inside the editor are lost the first time you add the plugin (like autocompletion until the script is fully loaded by the editor).

    For now, i discover that reloading the engine at least 2 times solves this (the first time you add the plugin folder and the second time after you activate the plugin) image

  • Translations not working as expected on typewrite animation

    Translations not working as expected on typewrite animation

    Hi, I found out that typewrite is currently using var l = node.text.length() this leads to getting translation key length instead of the actual translation text leght. In order to fix the issue I changed that line to var l = tr(node.text).length() so it now uses translation resolved text instead of translation key and it is fully compatible with non translated Strings.

    I was going to open a PR with the fix but I found out that typewrite sintax changed on your latest version and I don't know how to properly invoke tr function on that case.

  • Prevent having a null value on from and to property.

    Prevent having a null value on from and to property.

    The reason why to prevent this from is because this will give an error. This doesn't actually make sense for GDScript programmer because you don't actually had to put null on the value, but on those who is making a wrapper on other language to use this addon, this gets annoying, especially when working with relative values.

  • Call a bare funcref for on_started, w/o requiring an array.

    Call a bare funcref for on_started, w/o requiring an array.

    The documentation mentions that on_started is a funcref, but the code expects an array (potentially a single element).

    This implementation should work for both a bare funcref and an array of one or more elements (first a funcref, rest are args).

  • Update plugin.cfg

    Update plugin.cfg

    Seems like the plugin name is "Shapes" (you can see it in Godot plugin dock and inside this repository) but this plugin repository and the reference for the plugin it's "Anima".

    This can generate confusions in the future.

  • Make future releases to be just the addon

    Make future releases to be just the addon

    I'll try this plugin, seems cool, but in the meanwhile, i want to suggest to make future releases to be just the addon folder or the anima plugin folder, not the entire repository source code.

    This way, everyone can download only the plugin and also keep it updated via git.

  • Not Support shader_param?

    Not Support shader_param?

    godot: 3.5.1 anima: 0.3.2 I found shader_param in doc is error. use shared_param?

    var anima = Anima.begin(self, 'al2')
    anima.then({node = $Sprite, property = "material:shader_param/DissolveRate", from = -1.0, to = 1.0, duration = 1})
    anima.then({node = self, property = "opacity", from = 1, to = 0, duration = 0.28})
    anima.play()
    

    but not work

    image

    then I used Tween, luckily is correct

    var t = $Sprite/Tween.interpolate_property($Sprite, "material:shader_param/DissolveRate", -1, 1, 1)
    $Sprite/Tween.start()
    
  • not working for .gde files

    not working for .gde files

    https://github.com/ceceppa/anima/blob/b61ee6fb6a32824580c0d8f80b386dce259878c1/addons/anima/utils/animations.gd#L22

    The first if statement is always true: file.find('.gd.') < 0

    The second if statement is also match for both .gd file and .gdc file ,which makes it's quite confusion

    and I guess its not working for gde file, I use a low version of anima , and it report cant find any animation

    in replacement:

    		for file in list:
    			if file.ends_with('.gdc'):
    				filtered.push_back(file.replace('.gdc', '.gd'))
    			elif file.ends_with('.gde'):
    				filtered.push_back(file.replace('.gde', '.gd'))
    			elif file.ends_with('.gd'):
    				filtered.push_back(file)
    		_animations_list = filtered
    

    BTW, Anima is a great plugin ! Thanks a lot !

  • GLES3 causes lockup for 30-45 seconds in the 3d demos

    GLES3 causes lockup for 30-45 seconds in the 3d demos

    Please see this relevant Godot issue:

    https://github.com/godotengine/godot/issues/56670

    Perhaps we could move to GLES2 export for the demo example to prevent issues with GLES3 shader compilation?

  • Structure proposal

    Structure proposal

    You seem to be using the same class (AnimaNode) for everything right but this makes it hard to maintain and possibly prone to errors because you have to pass dictionaries with properties that sometimes are not compatible with each other. Plus users will have to remember all the names of the properties they have to pass. A better approach would be to have a different class for each type of animation. An example would be:

    # Create a class named AnimaAnimationGrid (or something similar)
    # then pass the type of the animation into the Begin method so this would return an AnimaAnimationGrid node instead of a generic AnimaNode.
    # With that in place now you can have proper properties for the methods instead of dictionaries (kind of like tween but with all of the nice features your project provieds)
    var anima := Anima.Begin(AnimaAnimations.Grid, self)
    anima.then(
       grid: $Grid,
       grid_size: grid_size,
       animation_type: Anima.GRID.COLUMNS_EVEN,
       property: "x",
       to: 5, 
       relative: true,
       duration: 0.3,
       easing: Anima.EASING.EASE_OUT_SINE,
       items_delay: 0
    )
    

    That way users wont have to go back to the documentation in order to check which parameters they can pass etc...

    EDIT: And of course have a base class from which all of the animations inherit

  • Hide strategy proposal and a bug report

    Hide strategy proposal and a bug report

    [PROPOSAL] Although the hide strategy is nice and in most cases more than enough, there are times where i would prefer for example to have an initial value for position or size instead of visibility or transparency. An interesting solution would be to have an additional property initial_value which sets all the nodes to the value before the animation begins. Of course all of this could be done manually (setting the size of the nodes before the animation starts for example) but since anima already iterates through the objects it would be convenient if there was a built in property.

    [BUG] Also when using anima.set_visibility_strategy(Anima.VISIBILITY.TRANSPARENT_ONLY) with a group animation the changes the scale of the controls, the controls never came back to be visible. I would expect them to become visible once the animation starts. I had to animate modulate to overcome this:

    anima.with({
      group = games_container,
      items_delay = 0.05,
      property = "modulate:a",
      from = 0,
      to = 1
    })
    
Related tags
GoDynamic can load and run Golang dynamic library compiled by -buildmode=shared -linkshared

GoDynamic can load and run Golang dynamic library compiled by -buildmode=shared -linkshared How does it work? GoDynamic works like a dynamic

Sep 30, 2022
EGo lets you build, debug und run Go apps on Intel SGX - as simple as conventional Go programming!

EGo lets you build, debug und run Go apps on Intel SGX - as simple as conventional Go programming!

Dec 28, 2022
To run a .go file use below syntax

To run a .go file use below syntax

Nov 2, 2021
This Go package allows you to set handler functions that run when named events occur

This Go package allows you to set handler functions that run when named events occur

Feb 10, 2022
Code Generation for Functional Programming, Concurrency and Generics in Golang

goderive goderive derives mundane golang functions that you do not want to maintain and keeps them up to date. It does this by parsing your go code fo

Dec 25, 2022
Go library that provides fuzzy string matching optimized for filenames and code symbols in the style of Sublime Text, VSCode, IntelliJ IDEA et al.
Go library that provides fuzzy string matching optimized for filenames and code symbols in the style of Sublime Text, VSCode, IntelliJ IDEA et al.

Go library that provides fuzzy string matching optimized for filenames and code symbols in the style of Sublime Text, VSCode, IntelliJ IDEA et al. This library is external dependency-free. It only depends on the Go standard library.

Dec 27, 2022
this is an api that execute your deno code and send you the output

this a simple api that execute your deno code and send you the output, has not limit per request example request: in deno: const rawResponse = await f

Dec 23, 2022
efaceconv - Code generation tool for high performance conversion from interface{} to immutable type without allocations.

efaceconv High performance conversion from interface{} to immutable types without additional allocations This is tool for go generate and common lib (

May 14, 2022
Type-driven code generation for Go

What’s this? gen is a code-generation tool for Go. It’s intended to offer generics-like functionality on your types. Out of the box, it offers offers

Jan 4, 2023
Versatile Go code generator.
Versatile Go code generator.

Generis Versatile Go code generator. Description Generis is a lightweight code preprocessor adding the following features to the Go language : Generic

Nov 30, 2022
Golang source code parsing, usage like reflect package

gotype Golang source code parsing, usage like reflect package English 简体中文 Usage API Documentation Examples License Pouch is licensed under the MIT Li

Dec 9, 2022
Code generation tools for Go.

interfaces Code generation tools for Go's interfaces. Tools available in this repository: cmd/interfacer cmd/structer cmd/interfacer Generates an inte

Dec 23, 2022
Jennifer is a code generator for Go

Jennifer Jennifer is a code generator for Go. package main import ( "fmt" . "github.com/dave/jennifer/jen" ) func main() { f := NewFile("m

Jan 4, 2023
bebop is a bebop parser written in Go, for generating Go code.

bebop is a bebop parser written in Go, for generating Go code. bebop can read .bop files and output .go files representing them: package main i

Dec 24, 2022
Reload Go code in a running process at function/method level granularity

got reload? Function/method-level stateful hot reloading for Go! Status Very much work in progress.

Nov 9, 2022
Example code for Go generics

go-generics-example Example code for Go generics. Usage $ go build -gcflags=-G=3 Requirements Go 1.17 or later Advertise Go 言語にやってくる Generics は我々に何をも

Dec 30, 2022
Hotswap provides a solution for reloading your go code without restarting your server, interrupting or blocking any ongoing procedure.
Hotswap provides a solution for reloading your go code without restarting your server, interrupting or blocking any ongoing procedure.

Hotswap provides a solution for reloading your go code without restarting your server, interrupting or blocking any ongoing procedure. Hotswap is built upon the plugin mechanism.

Jan 5, 2023
this is a easy breaker by golang code

tfgo-breaker 1. Intro This is a easy breaker by golang code. U can use it in your project quickly. Support function break, timeout, auto dry-run. 2. D

Sep 17, 2022
Source code of Liteloader Tools

LiteLoader Tools This repository store the source code of some LiteLoader Tools Prebuilt Binary see /bin folder Image2Binary [Golang] convert Image(jp

Aug 30, 2022