• 2D
  • animating line2d.points does not seem possible even if its a property.

The godot docs claim any property may be animated, yet I find that

neither

var _0_:Array = [Vector2(0, 0), Vector2(100, 0)]
var _1_:Array = [Vector2(0, 0), Vector2(100, 200)]

add_property_track(animation, 0, stroke, 'points'
add_property_track_key(animation, 0, 0.0, _0_)
add_property_track_key(animation, 0, 3.0, _1_)

or var 0:PoolVector2Array = PoolVector2Array([Vector2(0, 0), Vector2(100, 0)]) var 1: PoolVector2Array = PoolVector2Array( [Vector2(0, 0), Vector2(100, 200)]) add_property_track(animation, 0, stroke, 'points') add_property_track_key(animation, 0, 0.0, 0) add_property_track_key(animation, 0, 3.0, 1)

work and have no complaints from the engine.

I have to think the simple fact that PoolVector2Pool are read only after construction, that interpolating their values is non-sensical.

So the basic question, is this supposed to be even possible?

afaik PoolVector2Array is not read-only and it can normally be animated.

Check this project and press the spacebar. May give you some ideas.

@cybereality reality thanks for the reference.

so basically there is a means to do it, but nothing in the animation documentation points individuals to the node.

the problem here is Tween is completely disjoint from the animation system, such as player and the rest. sigh.

the other issue i see while you make a line2d's point a property, i need to animate a line2d points (as in poly line) programmatically where the polyline defined and animated is defined at run time. it isn't some static pre-built polyline

I stand corrected, option B does work. I think i just need continuous update to make it smooth instead of jumping.

continuous doesn't change the jumping.

i am beginning to think that using bones and mesh deformation maybe the only way to do this.

My same method would work with an animation player too. Except you don't animate the points directly. You animate properties on an object, and then the object updates the points every frame.

Here's completely runtime animated plain PoolVector2Array. Just attach the script to any 2d node and observe the value of a:

extends Node2D

var a: PoolVector2Array

func _ready():
	var anim_player = AnimationPlayer.new()
	self.add_child(anim_player)

	var anim = Animation.new()
	anim_player.add_animation("anim", anim)
	var track = anim.add_track(Animation.TYPE_VALUE)
	anim.track_set_path(track, ".:a" )
	anim.track_insert_key(track, 0, PoolVector2Array( [Vector2(0,0), Vector2(100,100) ] ))
	anim.track_insert_key(track, 1, PoolVector2Array( [Vector2(100,100), Vector2(0,0) ] ))
	anim.loop = true
	anim_player.play("anim")
	
func _process(delta):
	print(a)

So you're animating a pool of vectors not associated with a line2d.

How does this solve anything?

Because even if it is altering the pool vector array it isn't being rendered and at each frame. The pool vector would have to be set into a line 2d on each frame.

So I tried animating the vector pool array as above and added a method call on the very property.

The property doesn't change values tween keyframes. Simply put it seems like the engine silently bails either computing or updating to a vector pool array. This makes sense since these built ins are read only after construction.

Animation player isn't doing much if for every animation frame you must call a function to update properties, so it seems I can either go down the route of using polygon2d and skeletons animating them (which has a use case for me anyway) or figure out a way to animate the points I want and render it tough some other means

https://docs.godotengine.org/en/stable/tutorials/2d/custom_drawing_in_2d.html

@dotted said: How does this solve anything?

Just set the points equal to a each frame and it animates.

func _process(_delta):
	$Line2D.points = a

Actually, it works fine animating the points directly. You don't need the extra a variable.

func _ready():
	var anim_player = AnimationPlayer.new()
	self.add_child(anim_player)
	var anim = Animation.new()
	anim_player.add_animation("anim", anim)
	var track = anim.add_track(Animation.TYPE_VALUE)
	anim.track_set_path(track, "Line2D:points" )
	anim.track_insert_key(track, 0, PoolVector2Array( [ Vector2(336, 87), Vector2(204, 436), Vector2(735, 424), Vector2(629, 201)] ))
	anim.track_insert_key(track, 1, PoolVector2Array( [ Vector2(336, 87), Vector2(740, 481), Vector2(800, 305), Vector2(629, 201)] ))
	anim.loop = true
	anim_player.play("anim")

huh.. i stand corrected. why the heck didn't any of the same code work?

@dotted said: So you're animating a pool of vectors not associated with a line2d.

How does this solve anything?

Because even if it is altering the pool vector array it isn't being rendered and at each frame. The pool vector would have to be set into a line 2d on each frame.

Just animate it directly as @cybereality pointed out. My code example just demonstrates you can animate any PoolVector2Array be it a custom class property or built-in class/node property. Not sure why you're having problems with it. Of course, you cannot animate local variables as that wouldn't make any sense since they cannot survive between frames.

The bottom line is - you can animate any class level property/variable of any built-in (variant) type, either with AnimationPlayer or Tween. If you're still having problems, post a minimal project that replicates it and we'll take a look.

@cybereality said:

@dotted said: How does this solve anything?

Just set the points equal to a each frame and it animates.

func _process(_delta):
	$Line2D.points = a

But that would obviate much of the value of using an animation player.

I prolly set the wrong parameters to add track.

as an aside:

It is a little annoying that godot expresses an enum as Animation.TYPE_METHOD as this is not how TYPE_METHOD is documented as it is listed under a enum of TrackType.

Animation.TrackType.TYPE_METHOD fails as a valid reference during runtime only but the enum is specified under the class and the editor is happy with the statement.

I still wonder if under the hood the pool vector array isn't wholly duplicated. Pool arrays are copied on write.

@dotted said: huh.. i stand corrected. why the heck didn't any of the same code work?

If the script is on the Line2D, you have to refer to self properties like this:

anim.track_set_path(track, ".:points" )

@dotted said: as an aside:

It is a little annoying that godot expresses an enum as Animation.TYPE_METHOD as this is not how TYPE_METHOD is documented as it is listed under a enum of TrackType.

Animation.TrackType.TYPE_METHOD fails as a valid reference during runtime only but the enum is specified under the class and the editor is happy with the statement.

TrackType is not a defined namespace. It's an anonymous enum, so you should just treat its values as class constants. Name in docs is just for clarity. This is the case with all built-in class enums in Godot.

TrackType is not a defined namespace. It's an anonymous enum, so you should just treat its values as class constants. Name in docs is just for clarity. This is the case with all built-in class enums in Godot.

So you don't agree that the editor's satisfaction with Animtion.UpdateType.FOO which results in a runtime error that this construct is invalid is not very nice?

I am at a loss. That's saying to every body trying out the engine to go stuff themselves. There's standard book on user interface design and experience, GUI Bloopers. This breaks one of the basics of UX, by misleading the user.

@cybereality said:

@dotted said: huh.. i stand corrected. why the heck didn't any of the same code work?

If the script is on the Line2D, you have to refer to self properties like this:

anim.track_set_path(track, ".:points" )

That was not the issue, that was the very path I had used initially before asking the question. The problem arose rather when I created the track and didn't capture the track id, at least I think. Since it was track id 1, the value was perhaps interpreted as update type in another call, as this is the value of Animation.UPDATE_DISCRETE.

I was a bit annoyed at the time because the editor accepts Animation.UpdateType.UPDATE_DISCRETE, which caused me to thrash in anger and confusion why the statement was in error at runtime and in the debugger...

As pointed out above one has to know ahead of time, perhaps by reading every last inch of godot documentation elsewhere, that this documentation is misleading, requiring Animation.UPDATE_DISCRETE be used instead.

Discrete update was the observed behavior.

anyway, cleaned up my mess. thanks for the help

@dotted said: So you don't agree that the editor's satisfaction with Animtion.UpdateType.FOO which results in a runtime error that this construct is invalid is not very nice?

Treatment of class-level enum constants is consistent throughout the whole api and documentation. Now you know the convention so you shouldn't have any problems with this in the future :)

Note that when you click on the type name in the docs it hyperlinks you to that type's reference page. If it is just an anonymous enum such as UpdateMode it'll just send you to enum values list. That's a clue it's not a named type. Again, this is consistent for all api classes. There's also auto-complete which will show you list of names that are defined inside a class namespace.

Correct, when you are writing code, it will auto-complete and show you the list of possible enum values, no need to even consult the documentation (unless you need to know what the difference is, if the naming is not clear).