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

Fix perform_node_renames handling of AnimationMixers track paths #84282

Merged
merged 1 commit into from
Nov 3, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 93 additions & 75 deletions editor/scene_tree_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "editor/plugins/script_editor_plugin.h"
#include "editor/reparent_dialog.h"
#include "editor/shader_create_dialog.h"
#include "scene/animation/animation_tree.h"
#include "scene/gui/check_box.h"
#include "scene/main/window.h"
#include "scene/property_utils.h"
Expand Down Expand Up @@ -1810,95 +1811,93 @@ void SceneTreeDock::perform_node_renames(Node *p_base, HashMap<Node *, NodePath>
return;
}

// Renaming node paths used in node properties.
List<PropertyInfo> properties;
p_base->get_property_list(&properties);

for (const PropertyInfo &E : properties) {
if (!(E.usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR))) {
continue;
}
String propertyname = E.name;
Variant old_variant = p_base->get(propertyname);
Variant updated_variant = old_variant;
if (_check_node_path_recursive(p_base, updated_variant, p_renames)) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->add_do_property(p_base, propertyname, updated_variant);
undo_redo->add_undo_property(p_base, propertyname, old_variant);
p_base->set(propertyname, updated_variant);
}
}

bool autorename_animation_tracks = bool(EDITOR_GET("editors/animation/autorename_animation_tracks"));

if (autorename_animation_tracks && Object::cast_to<AnimationPlayer>(p_base)) {
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_base);
List<StringName> anims;
ap->get_animation_list(&anims);
Node *root = ap->get_node(ap->get_root_node());
AnimationMixer *mixer = Object::cast_to<AnimationMixer>(p_base);
if (autorename_animation_tracks && mixer) {
// Don't rename if we're an AnimationTree pointing to an AnimationPlayer
bool points_to_other_animation_player = false;
AnimationTree *at = Object::cast_to<AnimationTree>(mixer);
if (at) {
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(at->get_node_or_null(at->get_animation_player()));
if (ap) {
points_to_other_animation_player = true;
}
}

if (root) {
HashMap<Node *, NodePath>::Iterator found_root_path = p_renames->find(root);
NodePath new_root_path = found_root_path ? found_root_path->value : root->get_path();
if (!new_root_path.is_empty()) { // No renaming if root node is deleted.
for (const StringName &E : anims) {
Ref<Animation> anim = ap->get_animation(E);
if (!r_rem_anims->has(anim)) {
r_rem_anims->insert(anim, HashSet<int>());
HashSet<int> &ran = r_rem_anims->find(anim)->value;
for (int i = 0; i < anim->get_track_count(); i++) {
ran.insert(i);
if (!points_to_other_animation_player) {
List<StringName> anims;
mixer->get_animation_list(&anims);
Node *root = mixer->get_node(mixer->get_root_node());

if (root) {
HashMap<Node *, NodePath>::Iterator found_root_path = p_renames->find(root);
NodePath new_root_path = found_root_path ? found_root_path->value : root->get_path();
if (!new_root_path.is_empty()) { // No renaming if root node is deleted.
for (const StringName &E : anims) {
Ref<Animation> anim = mixer->get_animation(E);
if (!r_rem_anims->has(anim)) {
r_rem_anims->insert(anim, HashSet<int>());
HashSet<int> &ran = r_rem_anims->find(anim)->value;
for (int i = 0; i < anim->get_track_count(); i++) {
ran.insert(i);
}
}
}

HashSet<int> &ran = r_rem_anims->find(anim)->value;

if (anim.is_null()) {
continue;
}

int tracks_removed = 0;
HashSet<int> &ran = r_rem_anims->find(anim)->value;

for (int i = 0; i < anim->get_track_count(); i++) {
NodePath track_np = anim->track_get_path(i);
Node *n = root->get_node_or_null(track_np);
if (!n) {
if (anim.is_null() || EditorNode::get_singleton()->is_resource_read_only(anim)) {
continue;
}

if (!ran.has(i)) {
continue; //channel was removed
}
int tracks_removed = 0;

HashMap<Node *, NodePath>::Iterator found_path = p_renames->find(n);
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
if (found_path) {
if (found_path->value.is_empty()) {
//will be erased

int idx = i - tracks_removed;
tracks_removed++;

undo_redo->add_do_method(anim.ptr(), "remove_track", idx);
undo_redo->add_undo_method(anim.ptr(), "add_track", anim->track_get_type(i), idx);
undo_redo->add_undo_method(anim.ptr(), "track_set_path", idx, track_np);
undo_redo->add_undo_method(anim.ptr(), "track_set_interpolation_type", idx, anim->track_get_interpolation_type(i));
for (int j = 0; j < anim->track_get_key_count(i); j++) {
undo_redo->add_undo_method(anim.ptr(), "track_insert_key", idx, anim->track_get_key_time(i, j), anim->track_get_key_value(i, j), anim->track_get_key_transition(i, j));
}
for (int i = 0; i < anim->get_track_count(); i++) {
if (anim->track_is_imported(i)) {
continue;
}
SaracenOne marked this conversation as resolved.
Show resolved Hide resolved

ran.erase(i); //byebye channel
NodePath track_np = anim->track_get_path(i);

} else {
//will be renamed
NodePath rel_path = new_root_path.rel_path_to(found_path->value);
Node *n = root->get_node_or_null(track_np);
if (!n) {
continue;
}

NodePath new_path = NodePath(rel_path.get_names(), track_np.get_subnames(), false);
if (new_path == track_np) {
continue; //bleh
if (!ran.has(i)) {
continue; //channel was removed
}

HashMap<Node *, NodePath>::Iterator found_path = p_renames->find(n);
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
if (found_path) {
if (found_path->value.is_empty()) {
//will be erased

int idx = i - tracks_removed;
tracks_removed++;

undo_redo->add_do_method(anim.ptr(), "remove_track", idx);
undo_redo->add_undo_method(anim.ptr(), "add_track", anim->track_get_type(i), idx);
undo_redo->add_undo_method(anim.ptr(), "track_set_path", idx, track_np);
undo_redo->add_undo_method(anim.ptr(), "track_set_interpolation_type", idx, anim->track_get_interpolation_type(i));
for (int j = 0; j < anim->track_get_key_count(i); j++) {
undo_redo->add_undo_method(anim.ptr(), "track_insert_key", idx, anim->track_get_key_time(i, j), anim->track_get_key_value(i, j), anim->track_get_key_transition(i, j));
}

ran.erase(i); //byebye channel

} else {
//will be renamed
NodePath rel_path = new_root_path.rel_path_to(found_path->value);

NodePath new_path = NodePath(rel_path.get_names(), track_np.get_subnames(), false);
if (new_path == track_np) {
continue; //bleh
}
undo_redo->add_do_method(anim.ptr(), "track_set_path", i, new_path);
undo_redo->add_undo_method(anim.ptr(), "track_set_path", i, track_np);
}
undo_redo->add_do_method(anim.ptr(), "track_set_path", i, new_path);
undo_redo->add_undo_method(anim.ptr(), "track_set_path", i, track_np);
}
}
}
Expand All @@ -1907,6 +1906,25 @@ void SceneTreeDock::perform_node_renames(Node *p_base, HashMap<Node *, NodePath>
}
}

// Renaming node paths used in node properties.
List<PropertyInfo> properties;
p_base->get_property_list(&properties);

for (const PropertyInfo &E : properties) {
if (!(E.usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR))) {
continue;
}
String propertyname = E.name;
Variant old_variant = p_base->get(propertyname);
Variant updated_variant = old_variant;
if (_check_node_path_recursive(p_base, updated_variant, p_renames)) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->add_do_property(p_base, propertyname, updated_variant);
undo_redo->add_undo_property(p_base, propertyname, old_variant);
p_base->set(propertyname, updated_variant);
}
}

for (int i = 0; i < p_base->get_child_count(); i++) {
perform_node_renames(p_base->get_child(i), p_renames, r_rem_anims);
}
Expand Down
Loading