Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose low level properties of animation_tree #77347

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Daylily-Zeleen
Copy link
Contributor

Implement #6807.

Expose some low level properties of AnimationTree to realize recordable animation system.

AnimRecord.2.mp4

@Daylily-Zeleen Daylily-Zeleen requested review from a team as code owners May 22, 2023 13:01
@Daylily-Zeleen Daylily-Zeleen force-pushed the daylily-zeleen/anim_tree_expose branch 3 times, most recently from da8ca9f to 85b6f3b Compare May 22, 2023 13:05
@TokageItLab
Copy link
Member

TokageItLab commented May 22, 2023

It is okay to add a way to get some informations, but there are some properties that should not have setter and they should be readonly.

We must avoid the possibility of users doing unsafe access by publishing properties. It would easily break AniamtionTree's internal processes.

If you want to have rollback features as described in the proposal, you need to implement a secure API that can handle the rollback without breaking those properties.

If you want to do something like the video, you can add a class like AnimationTreeRecorder that extends AnimationTree with properties like "buffer time" and "rollback time" to record and rollback the state. I think it would be more acceptable to add that to the core than to publish these properties.

@Daylily-Zeleen
Copy link
Contributor Author

Daylily-Zeleen commented May 23, 2023

This solution is very basic and unsafe, but not unreasonable.
Like RefCounted::reference() and RefCounted::unreference(), we can mark these exposed properties with description that "Use this only if you really know what you are doing".

Although I can't provide other use case of exposing low level properties, I think this pr can do more thing, not only for rollback feature.
Of course, current implement need to be optimized.
Some properties like "state_xxx" may should be combined as one object to make sense (it means that they should be set together, in order to not break internal processes), and hide its details.

If you want to do something like the video, you can add a class like AnimationTreeRecorder that extends AnimationTree with properties like "buffer time" and "rollback time" to record and rollback the state. I think it would be more acceptable to add that to the core than to publish these properties.

Rollback feature is quite specific and non-universal, I am not sure it is worth to add a class to do this.
If it is worth, it will more high performance and safe, I prefer this way, too.

By the way, I still not clearify that which properties should be retrieved when process rollbacking (I remain comments in code to describe my understanding and why not publish them), I need help.

@TokageItLab
Copy link
Member

TokageItLab commented May 23, 2023

Godot basically can't implement something for which there is no use case to the core. This means that we cannot publish these dangerous properties without a reason.

I agree that there are practical use cases where it is worthwhile to implement rollback for replays of rhythm games where the characters dance, or for online play.

So I think it is better to brush up the functionality for rollback to increase the generic utility of it than to focus on publishing these properties.

@Daylily-Zeleen
Copy link
Contributor Author

Daylily-Zeleen commented May 23, 2023

If we agree that "rollback" can be a generic utility of godot animation system, I will design function-oriented apis instead of publishing properties.

Here have two set of apis by adding a class AnimationTreeRecorder that extends AnimationTree ( or modify AnimationTree directly):

  1. Manage record buffer internally:

    • int max_record_bufer_size = 1024: when set this property, it will resize the record buffer if current buffer size greater then target max size.
    • int get_record_buffer_size() : return the current record buffer size.
    • int save_record(int p_record_index = -1) : save current state and return the buffer index, if p_record_index >= 0, it can be used to override record.
    • bool load_recod(int p_record_index, bool p_clean_records_after_target_index = true): if p_clean_records_after_target_index == true, it will clean records which index greater than p_record_index (in other words, to resize internal records buffer, its type may be Vector), return successful or not.
  2. Manage recods by developers themselves, only provide methods to get and set state:

    • Ref<AnimationTreeState> get_animation_tree_state()
    • bool set_animation_tree_state(Ref<AnimationTreeState> state) : return successful or not.

The first way seem more high performance, but the second way is more simple and easy to use.
I am not sure which solution is better.


No matter which option I choose, I need to clearify which low level properties should be gathered as "State/Record". This is an important topic, too.

@TokageItLab
Copy link
Member

TokageItLab commented May 23, 2023

The former looks better. However, I don't see the need to call save_record() manually. It would be okay to have it, but it should be an additional feature, like AnimationTree::advance().

Instead, it would be fine to have a recording_enabled, and a recording_rate as frame or delta gap.

@Daylily-Zeleen
Copy link
Contributor Author

Let's do some change:

For automatically time base recording, add recording_enabled and recording_rate for ANIMATION_PROCESS_PHYSICS and ANIMATION_PROCESS_IDLE. (recording_rate is float value of recording gap in second).

For manually record, change AnimationTree::advance(double p_time) to AnimationTree::advance(double p_time, bool p_record = false), and not concern about recording_enabled.

scene/animation/animation_tree.h Outdated Show resolved Hide resolved
// "input_activity_map" is updated when update properties, expose it is not make sense.
// It seem "input_activity_map_get" only used in edior.
// "properties_dirty", "last_animation_player" are changed automatically and not effect the work logic, expose them is not make sense.
// ================================
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several comments explaining things that I don't think are helpful here

@fire
Copy link
Member

fire commented May 23, 2023

Did we expose the ring buffer implementation in Godot Engine to GDScript?

I don't think we ever did.

https://github.com/godotengine/godot/blob/master/core/templates/ring_buffer.h

A RingBuffer was mentioned in get_record_buffer_size of the above design.

@Daylily-Zeleen Daylily-Zeleen marked this pull request as draft May 24, 2023 03:28
@Daylily-Zeleen Daylily-Zeleen force-pushed the daylily-zeleen/anim_tree_expose branch from 890d806 to ce4adb4 Compare May 24, 2023 09:05
@Daylily-Zeleen Daylily-Zeleen force-pushed the daylily-zeleen/anim_tree_expose branch from ce4adb4 to 991be6e Compare May 24, 2023 09:12
@AThousandShips
Copy link
Member

Using --doctool on your own built version will help finding all the instances (be careful if you're building with double precision, it will give the wrong results in some places)

<member name="property_map" type="Dictionary" setter="set_property_map" getter="get_property_map" default="{}">
</member>
<member name="root_motion_position" type="Vector3" setter="set_root_motion_position" getter="get_root_motion_position" default="Vector3(0, 0, 0)">
Retrieve the motion delta of position with the [member root_motion_track] as a [Vector3] that can be used elsewhere.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of the text here is still for a function just getting the value, needs a new wording

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My English is not goodt. Although I update the description, it need review.

@Daylily-Zeleen Daylily-Zeleen force-pushed the daylily-zeleen/anim_tree_expose branch 4 times, most recently from b5f6b57 to db5feb2 Compare May 24, 2023 11:35
@Daylily-Zeleen Daylily-Zeleen force-pushed the daylily-zeleen/anim_tree_expose branch from db5feb2 to 82691f1 Compare May 24, 2023 11:38
@Daylily-Zeleen
Copy link
Contributor Author

Did we expose the ring buffer implementation in Godot Engine to GDScript?

I don't think we ever did.

https://github.com/godotengine/godot/blob/master/core/templates/ring_buffer.h

A RingBuffer was mentioned in get_record_buffer_size of the above design.

In #77395, I add a new template CircularDeque to handle this use case, please communicate in #77395.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants