godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Directly import frames in AnimationPlayer from AnimationSprite or a spritesheet #3268

Open jordanlis opened 3 years ago

jordanlis commented 3 years ago

Describe the project you are working on

2D sidescroller

Describe the problem or limitation you are having in your project

In order to animate living beings or other objects in my game, I have the following process

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I would like to have a button in the animation editor that will import a standard animation for a given AnimatedSprite. 2 things are needed :

This will prevent clicking 2 or 3 times for creating each frame and it will improve user experience.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

New button 5b1961771e56d290557236(1)

Then, you select the node and optionnally the animation in a popin

If this enhancement will not be used often, can it be worked around with a few lines of script?

No (or I don't see how, but I'm not a great developer)

Is there a reason why this should be core and not an add-on in the asset library?

AnimationPlayer is core

KoBeWi commented 3 years ago

I once made an editor script that will automatically create animation based on currently selected Sprite (i.e. makes hframes * vframes animation and populates the keys with consecutive frames). This is definitely doable with a plugin 🤔

jordanlis commented 3 years ago

I once made an editor script that will automatically create animation based on currently selected Sprite (i.e. makes hframes * vframes animation and populates the keys with consecutive frames). This is definitely doable with a plugin 🤔

I would definitely interested in using it, since I still think it should be core.

KoBeWi commented 3 years ago

This is the script I'm using:

tool
extends EditorScript

func _run() -> void:
    var sprite: Sprite = get_scene().get_node("Sprite")
    var animator: AnimationPlayer = get_scene().get_node("AnimationPlayer")

    assert(sprite and animator)

    var frames = sprite.hframes * sprite.vframes

    var anim_name = sprite.texture.resource_path.get_file().get_basename()
    if not animator.has_animation(anim_name):
        animator.add_animation(anim_name, Animation.new())

    var animation = animator.get_animation(anim_name)
    animation.length = frames

    var base_path = str(animator.get_node(animator.root_node).get_path_to(sprite))

    for i in frames:
        animation.track_insert_key(0, i, i)

    animation.add_track(Animation.TYPE_VALUE)
    animation.track_set_path(1, base_path + ":texture")
    animation.track_insert_key(1, 0, sprite.texture)

    animation.add_track(Animation.TYPE_VALUE)
    animation.track_set_path(2, base_path + ":hframes")
    animation.track_insert_key(2, 0, sprite.hframes)

    animation.add_track(Animation.TYPE_VALUE)
    animation.track_set_path(3, base_path + ":vframes")
    animation.track_insert_key(3, 0, sprite.vframes)

    animation.add_track(Animation.TYPE_VALUE)
    animation.track_set_path(0, base_path + ":frame")
    animation.value_track_set_update_mode(0, Animation.UPDATE_DISCRETE)

It's hardcoded to create animation in node "AnimationPlayer" based on node "Sprite", but you can modify it to your needs.