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

Allow keying properties when selecting multiple nodes #92842

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
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
132 changes: 35 additions & 97 deletions editor/animation_track_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "editor/gui/editor_spin_slider.h"
#include "editor/gui/scene_tree_editor.h"
#include "editor/inspector_dock.h"
#include "editor/multi_node_edit.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/themes/editor_scale.h"
#include "scene/3d/mesh_instance_3d.h"
Expand Down Expand Up @@ -3627,7 +3628,7 @@ void AnimationTrackEditor::update_keying() {
EditorSelectionHistory *editor_history = EditorNode::get_singleton()->get_editor_selection_history();
if (is_visible_in_tree() && animation.is_valid() && editor_history->get_path_size() > 0) {
Object *obj = ObjectDB::get_instance(editor_history->get_path_object(0));
keying_enabled = Object::cast_to<Node>(obj) != nullptr;
keying_enabled = Object::cast_to<Node>(obj) != nullptr || Object::cast_to<MultiNodeEdit>(obj) != nullptr;
}

if (keying_enabled == keying) {
Expand Down Expand Up @@ -4044,19 +4045,20 @@ void AnimationTrackEditor::_insert_animation_key(NodePath p_path, const Variant
_query_insert(id);
}

void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists) {
void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_property, bool p_only_if_exists, bool p_advance) {
ERR_FAIL_NULL(root);

// Let's build a node path.
Node *node = p_node;
String path = root->get_path_to(node, true);
String path = root->get_path_to(p_node, true);

Variant value = p_node->get(p_property);

if (Object::cast_to<AnimationPlayer>(node) && p_property == "current_animation") {
if (node == AnimationPlayerEditor::get_singleton()->get_player()) {
if (Object::cast_to<AnimationPlayer>(p_node) && p_property == "current_animation") {
if (p_node == AnimationPlayerEditor::get_singleton()->get_player()) {
EditorNode::get_singleton()->show_warning(TTR("AnimationPlayer can't animate itself, only other players."));
return;
}
_insert_animation_key(path, p_value);
_insert_animation_key(path, value);
return;
}

Expand Down Expand Up @@ -4084,26 +4086,26 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
InsertData id;
id.path = np;
id.track_idx = i;
id.value = p_value;
id.value = value;
id.type = Animation::TYPE_VALUE;
// TRANSLATORS: This describes the target of new animation track, will be inserted into another string.
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = false;
id.advance = p_advance;
// Dialog insert.
_query_insert(id);
inserted = true;
} else if (animation->track_get_type(i) == Animation::TYPE_BEZIER) {
Variant value;
Variant actual_value;
String track_path = animation->track_get_path(i);
if (track_path == np) {
value = p_value; // All good.
actual_value = value; // All good.
} else {
int sep = track_path.rfind(":");
if (sep != -1) {
String base_path = track_path.substr(0, sep);
if (base_path == np) {
String value_name = track_path.substr(sep + 1);
value = p_value.get(value_name);
actual_value = value.get(value_name);
} else {
continue;
}
Expand All @@ -4115,10 +4117,10 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
InsertData id;
id.path = animation->track_get_path(i);
id.track_idx = i;
id.value = value;
id.value = actual_value;
id.type = Animation::TYPE_BEZIER;
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = false;
id.advance = p_advance;
// Dialog insert.
_query_insert(id);
inserted = true;
Expand All @@ -4131,105 +4133,41 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
InsertData id;
id.path = np;
id.track_idx = -1;
id.value = p_value;
id.value = value;
id.type = Animation::TYPE_VALUE;
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = false;
id.advance = p_advance;
// Dialog insert.
_query_insert(id);
}

void AnimationTrackEditor::insert_value_key(const String &p_property, const Variant &p_value, bool p_advance) {
void AnimationTrackEditor::insert_value_key(const String &p_property, bool p_advance) {
EditorSelectionHistory *history = EditorNode::get_singleton()->get_editor_selection_history();

ERR_FAIL_NULL(root);
ERR_FAIL_COND(history->get_path_size() == 0);
Object *obj = ObjectDB::get_instance(history->get_path_object(0));
ERR_FAIL_NULL(Object::cast_to<Node>(obj));

// Let's build a node path.
Node *node = Object::cast_to<Node>(obj);
String path = root->get_path_to(node, true);

if (Object::cast_to<AnimationPlayer>(node) && p_property == "current_animation") {
if (node == AnimationPlayerEditor::get_singleton()->get_player()) {
EditorNode::get_singleton()->show_warning(TTR("AnimationPlayer can't animate itself, only other players."));
return;
}
_insert_animation_key(path, p_value);
return;
}

for (int i = 1; i < history->get_path_size(); i++) {
String prop = history->get_path_property(i);
ERR_FAIL_COND(prop.is_empty());
path += ":" + prop;
}

path += ":" + p_property;

NodePath np = path;
Ref<MultiNodeEdit> multi_node_edit(obj);
if (multi_node_edit.is_valid()) {
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
ERR_FAIL_NULL(edited_scene);

// Locate track.

bool inserted = false;
make_insert_queue();

make_insert_queue();
for (int i = 0; i < animation->get_track_count(); i++) {
if (animation->track_get_type(i) == Animation::TYPE_VALUE) {
if (animation->track_get_path(i) != np) {
continue;
}

InsertData id;
id.path = np;
id.track_idx = i;
id.value = p_value;
id.type = Animation::TYPE_VALUE;
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = p_advance;
// Dialog insert.
_query_insert(id);
inserted = true;
} else if (animation->track_get_type(i) == Animation::TYPE_BEZIER) {
Variant value;
if (animation->track_get_path(i) == np) {
value = p_value; // All good.
} else {
String tpath = animation->track_get_path(i);
int index = tpath.rfind(":");
if (NodePath(tpath.substr(0, index + 1)) == np) {
String subindex = tpath.substr(index + 1, tpath.length() - index);
value = p_value.get(subindex);
} else {
continue;
}
}

InsertData id;
id.path = animation->track_get_path(i);
id.track_idx = i;
id.value = value;
id.type = Animation::TYPE_BEZIER;
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = p_advance;
// Dialog insert.
_query_insert(id);
inserted = true;
for (int i = 0; i < multi_node_edit->get_node_count(); ++i) {
Node *node = edited_scene->get_node(multi_node_edit->get_node(i));
insert_node_value_key(node, p_property, false, p_advance);
}
}
commit_insert_queue();

if (!inserted) {
InsertData id;
id.path = np;
id.track_idx = -1;
id.value = p_value;
id.type = Animation::TYPE_VALUE;
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = p_advance;
// Dialog insert.
_query_insert(id);
commit_insert_queue();
} else {
Node *node = Object::cast_to<Node>(obj);
ERR_FAIL_NULL(node);

make_insert_queue();
insert_node_value_key(node, p_property, false, p_advance);
commit_insert_queue();
}
}

Expand Down
4 changes: 2 additions & 2 deletions editor/animation_track_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -712,8 +712,8 @@ class AnimationTrackEditor : public VBoxContainer {
void cleanup();

void set_anim_pos(float p_pos);
void insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists = false);
void insert_value_key(const String &p_property, const Variant &p_value, bool p_advance);
void insert_node_value_key(Node *p_node, const String &p_property, bool p_only_if_exists = false, bool p_advance = false);
void insert_value_key(const String &p_property, bool p_advance);
void insert_transform_key(Node3D *p_node, const String &p_sub, const Animation::TrackType p_type, const Variant &p_value);
bool has_track(Node3D *p_node, const String &p_sub, const Animation::TrackType p_type);
void make_insert_queue();
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/animation_player_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2165,7 +2165,7 @@ void AnimationPlayerEditorPlugin::_property_keyed(const String &p_keyed, const V
return;
}
te->_clear_selection();
te->insert_value_key(p_keyed, p_value, p_advance);
te->insert_value_key(p_keyed, p_advance);
}

void AnimationPlayerEditorPlugin::_transform_key_request(Object *sp, const String &p_sub, const Transform3D &p_key) {
Expand Down
18 changes: 9 additions & 9 deletions editor/plugins/canvas_item_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4319,13 +4319,13 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
Node2D *n2d = Object::cast_to<Node2D>(ci);

if (key_pos && p_location) {
te->insert_node_value_key(n2d, "position", n2d->get_position(), p_on_existing);
te->insert_node_value_key(n2d, "position", p_on_existing);
}
if (key_rot && p_rotation) {
te->insert_node_value_key(n2d, "rotation", n2d->get_rotation(), p_on_existing);
te->insert_node_value_key(n2d, "rotation", p_on_existing);
}
if (key_scale && p_scale) {
te->insert_node_value_key(n2d, "scale", n2d->get_scale(), p_on_existing);
te->insert_node_value_key(n2d, "scale", p_on_existing);
}

if (n2d->has_meta("_edit_bone_") && n2d->get_parent_item()) {
Expand All @@ -4351,13 +4351,13 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
if (has_chain && ik_chain.size()) {
for (Node2D *&F : ik_chain) {
if (key_pos) {
te->insert_node_value_key(F, "position", F->get_position(), p_on_existing);
te->insert_node_value_key(F, "position", p_on_existing);
}
if (key_rot) {
te->insert_node_value_key(F, "rotation", F->get_rotation(), p_on_existing);
te->insert_node_value_key(F, "rotation", p_on_existing);
}
if (key_scale) {
te->insert_node_value_key(F, "scale", F->get_scale(), p_on_existing);
te->insert_node_value_key(F, "scale", p_on_existing);
}
}
}
Expand All @@ -4367,13 +4367,13 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
Control *ctrl = Object::cast_to<Control>(ci);

if (key_pos) {
te->insert_node_value_key(ctrl, "position", ctrl->get_position(), p_on_existing);
te->insert_node_value_key(ctrl, "position", p_on_existing);
}
if (key_rot) {
te->insert_node_value_key(ctrl, "rotation", ctrl->get_rotation(), p_on_existing);
te->insert_node_value_key(ctrl, "rotation", p_on_existing);
}
if (key_scale) {
te->insert_node_value_key(ctrl, "size", ctrl->get_size(), p_on_existing);
te->insert_node_value_key(ctrl, "size", p_on_existing);
}
}
}
Expand Down
Loading