summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/editor_spin_slider.cpp2
-rw-r--r--editor/import/post_import_plugin_skeleton_renamer.cpp2
-rw-r--r--editor/import/post_import_plugin_skeleton_rest_fixer.cpp348
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp12
-rw-r--r--editor/scene_tree_dock.cpp48
-rw-r--r--editor/scene_tree_dock.h4
6 files changed, 228 insertions, 188 deletions
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index 33632649c8..58020cf682 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -42,7 +42,7 @@ String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const {
#else
Key key = Key::CTRL;
#endif
- return TS->format_number(rtos(get_value())) + "\n\n" + vformat(TTR("Hold %s to round to integers. Hold Shift for more precise changes."), find_keycode_name(key));
+ return TS->format_number(rtos(get_value())) + "\n\n" + vformat(TTR("Hold %s to round to integers.\nHold Shift for more precise changes."), find_keycode_name(key));
}
return TS->format_number(rtos(get_value()));
}
diff --git a/editor/import/post_import_plugin_skeleton_renamer.cpp b/editor/import/post_import_plugin_skeleton_renamer.cpp
index 69c0a047e4..72ccb832c7 100644
--- a/editor/import/post_import_plugin_skeleton_renamer.cpp
+++ b/editor/import/post_import_plugin_skeleton_renamer.cpp
@@ -143,7 +143,7 @@ void PostImportPluginSkeletonRenamer::internal_process(InternalImportCategory p_
// Make unique skeleton.
if (bool(p_options["retarget/bone_renamer/unique_node/make_unique"])) {
String unique_name = String(p_options["retarget/bone_renamer/unique_node/skeleton_name"]);
- ERR_FAIL_COND_MSG(unique_name == String(), "Skeleton unique name cannot be empty.");
+ ERR_FAIL_COND_MSG(unique_name.is_empty(), "Skeleton unique name cannot be empty.");
TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
while (nodes.size()) {
diff --git a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp
index 6f775c7ea8..a5ef2e7f97 100644
--- a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp
+++ b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp
@@ -90,16 +90,9 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
}
}
- // Apply node transforms.
+ // Get global transform.
+ Transform3D global_transform;
if (bool(p_options["retarget/rest_fixer/apply_node_transforms"])) {
- LocalVector<Transform3D> old_skeleton_rest;
- LocalVector<Transform3D> old_skeleton_global_rest;
- for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
- old_skeleton_rest.push_back(src_skeleton->get_bone_rest(i));
- old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i));
- }
-
- Transform3D global_transform;
Node *pr = src_skeleton;
while (pr) {
Node3D *pr3d = Object::cast_to<Node3D>(pr);
@@ -109,6 +102,47 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
}
pr = pr->get_parent();
}
+ global_transform.origin = Vector3(); // Translation by a Node is not a bone animation, so the retargeted model should be at the origin.
+ }
+
+ // Calc IBM difference.
+ LocalVector<Vector<Transform3D>> ibm_diffs;
+ {
+ TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
+ while (nodes.size()) {
+ ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
+ ERR_CONTINUE(!mi);
+
+ Ref<Skin> skin = mi->get_skin();
+ ERR_CONTINUE(!skin.is_valid());
+
+ Node *node = mi->get_node(mi->get_skeleton_path());
+ ERR_CONTINUE(!node);
+
+ Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (!mesh_skeleton || mesh_skeleton != src_skeleton) {
+ continue;
+ }
+
+ Vector<Transform3D> ibm_diff;
+ ibm_diff.resize(src_skeleton->get_bone_count());
+ Transform3D *ibm_diff_w = ibm_diff.ptrw();
+
+ int skin_len = skin->get_bind_count();
+ for (int i = 0; i < skin_len; i++) {
+ StringName bn = skin->get_bind_name(i);
+ int bone_idx = src_skeleton->find_bone(bn);
+ if (bone_idx >= 0) {
+ ibm_diff_w[bone_idx] = global_transform * src_skeleton->get_bone_global_rest(bone_idx) * skin->get_bind_pose(i);
+ }
+ }
+
+ ibm_diffs.push_back(ibm_diff);
+ }
+ }
+
+ // Apply node transforms.
+ if (bool(p_options["retarget/rest_fixer/apply_node_transforms"])) {
Vector3 scl = global_transform.basis.get_scale_local();
Vector<int> bones_to_process = src_skeleton->get_parentless_bones();
@@ -148,38 +182,42 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
String track_path = String(anim->track_get_path(i).get_concatenated_names());
Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
- if (node) {
- Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
- if (track_skeleton && track_skeleton == src_skeleton) {
- StringName bn = anim->track_get_path(i).get_subname(0);
- if (bn) {
- int bone_idx = src_skeleton->find_bone(bn);
- int key_len = anim->track_get_key_count(i);
- if (anim->track_get_type(i) == Animation::TYPE_POSITION_3D) {
- if (bones_to_process.has(bone_idx)) {
- for (int j = 0; j < key_len; j++) {
- Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
- anim->track_set_key_value(i, j, global_transform.basis.xform(ps) + global_transform.origin);
- }
- } else {
- for (int j = 0; j < key_len; j++) {
- Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
- anim->track_set_key_value(i, j, ps * scl);
- }
- }
- } else if (bones_to_process.has(bone_idx)) {
- if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) {
- for (int j = 0; j < key_len; j++) {
- Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j));
- anim->track_set_key_value(i, j, global_transform.basis.get_rotation_quaternion() * qt);
- }
- } else {
- for (int j = 0; j < key_len; j++) {
- Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j)));
- anim->track_set_key_value(i, j, (global_transform.basis * sc).get_scale());
- }
- }
- }
+ ERR_CONTINUE(!node);
+
+ Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (!track_skeleton || track_skeleton != src_skeleton) {
+ continue;
+ }
+
+ StringName bn = anim->track_get_path(i).get_subname(0);
+ if (!bn) {
+ continue;
+ }
+
+ int bone_idx = src_skeleton->find_bone(bn);
+ int key_len = anim->track_get_key_count(i);
+ if (anim->track_get_type(i) == Animation::TYPE_POSITION_3D) {
+ if (bones_to_process.has(bone_idx)) {
+ for (int j = 0; j < key_len; j++) {
+ Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
+ anim->track_set_key_value(i, j, global_transform.basis.xform(ps) + global_transform.origin);
+ }
+ } else {
+ for (int j = 0; j < key_len; j++) {
+ Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
+ anim->track_set_key_value(i, j, ps * scl);
+ }
+ }
+ } else if (bones_to_process.has(bone_idx)) {
+ if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) {
+ for (int j = 0; j < key_len; j++) {
+ Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j));
+ anim->track_set_key_value(i, j, global_transform.basis.get_rotation_quaternion() * qt);
+ }
+ } else {
+ for (int j = 0; j < key_len; j++) {
+ Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j)));
+ anim->track_set_key_value(i, j, (global_transform.basis * sc).get_scale());
}
}
}
@@ -220,24 +258,26 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
}
}
- if (found_skeleton) {
- // Search and insert rot track if it doesn't exist.
- for (int prof_idx = 0; prof_idx < prof_skeleton->get_bone_count(); prof_idx++) {
- String bone_name = is_renamed ? prof_skeleton->get_bone_name(prof_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_idx)));
- if (bone_name == String()) {
- continue;
- }
- int src_idx = src_skeleton->find_bone(bone_name);
- if (src_idx == -1) {
- continue;
- }
- String insert_path = track_path + ":" + bone_name;
- int rot_track = anim->find_track(insert_path, Animation::TYPE_ROTATION_3D);
- if (rot_track == -1) {
- int track = anim->add_track(Animation::TYPE_ROTATION_3D);
- anim->track_set_path(track, insert_path);
- anim->rotation_track_insert_key(track, 0, src_skeleton->get_bone_rest(src_idx).basis.get_rotation_quaternion());
- }
+ if (!found_skeleton) {
+ continue;
+ }
+
+ // Search and insert rot track if it doesn't exist.
+ for (int prof_idx = 0; prof_idx < prof_skeleton->get_bone_count(); prof_idx++) {
+ String bone_name = is_renamed ? prof_skeleton->get_bone_name(prof_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_idx)));
+ if (bone_name.is_empty()) {
+ continue;
+ }
+ int src_idx = src_skeleton->find_bone(bone_name);
+ if (src_idx == -1) {
+ continue;
+ }
+ String insert_path = track_path + ":" + bone_name;
+ int rot_track = anim->find_track(insert_path, Animation::TYPE_ROTATION_3D);
+ if (rot_track == -1) {
+ int track = anim->add_track(Animation::TYPE_ROTATION_3D);
+ anim->track_set_path(track, insert_path);
+ anim->rotation_track_insert_key(track, 0, src_skeleton->get_bone_rest(src_idx).basis.get_rotation_quaternion());
}
}
}
@@ -385,19 +425,23 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
String track_path = String(anim->track_get_path(i).get_concatenated_names());
Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
- if (node) {
- Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
- if (track_skeleton && track_skeleton == src_skeleton) {
- StringName bn = anim->track_get_path(i).get_concatenated_subnames();
- if (bn == scale_base_bone_name) {
- int key_len = anim->track_get_key_count(i);
- for (int j = 0; j < key_len; j++) {
- Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j));
- pos.y += base_adjustment;
- anim->track_set_key_value(i, j, pos);
- }
- }
- }
+ ERR_CONTINUE(!node);
+
+ Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (!track_skeleton || track_skeleton != src_skeleton) {
+ continue;
+ }
+
+ StringName bn = anim->track_get_path(i).get_concatenated_subnames();
+ if (bn != scale_base_bone_name) {
+ continue;
+ }
+
+ int key_len = anim->track_get_key_count(i);
+ for (int j = 0; j < key_len; j++) {
+ Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j));
+ pos.y += base_adjustment;
+ anim->track_set_key_value(i, j, pos);
}
}
}
@@ -441,16 +485,18 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
String track_path = String(anim->track_get_path(i).get_concatenated_names());
Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
- if (node) {
- Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
- if (track_skeleton && track_skeleton == src_skeleton) {
- real_t mlt = 1 / src_skeleton->get_motion_scale();
- int key_len = anim->track_get_key_count(i);
- for (int j = 0; j < key_len; j++) {
- Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j));
- anim->track_set_key_value(i, j, pos * mlt);
- }
- }
+ ERR_CONTINUE(!node);
+
+ Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (!track_skeleton || track_skeleton != src_skeleton) {
+ continue;
+ }
+
+ real_t mlt = 1 / src_skeleton->get_motion_scale();
+ int key_len = anim->track_get_key_count(i);
+ for (int j = 0; j < key_len; j++) {
+ Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j));
+ anim->track_set_key_value(i, j, pos * mlt);
}
}
}
@@ -518,6 +564,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
while (nodes.size()) {
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
+ ERR_CONTINUE(!ap);
List<StringName> anims;
ap->get_animation_list(&anims);
for (const StringName &name : anims) {
@@ -534,53 +581,57 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
String track_path = String(anim->track_get_path(i).get_concatenated_names());
Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
- if (node) {
- Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
- if (track_skeleton && track_skeleton == src_skeleton) {
- StringName bn = anim->track_get_path(i).get_subname(0);
- if (bn) {
- int bone_idx = src_skeleton->find_bone(bn);
-
- Transform3D old_rest = old_skeleton_rest[bone_idx];
- Transform3D new_rest = src_skeleton->get_bone_rest(bone_idx);
- Transform3D old_pg;
- Transform3D new_pg;
- int parent_idx = src_skeleton->get_bone_parent(bone_idx);
- if (parent_idx >= 0) {
- old_pg = old_skeleton_global_rest[parent_idx];
- new_pg = src_skeleton->get_bone_global_rest(parent_idx);
- }
-
- int key_len = anim->track_get_key_count(i);
- if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) {
- Quaternion old_rest_q = old_rest.basis.get_rotation_quaternion();
- Quaternion new_rest_q = new_rest.basis.get_rotation_quaternion();
- Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion();
- Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion();
- for (int j = 0; j < key_len; j++) {
- Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j));
- anim->track_set_key_value(i, j, new_pg_q.inverse() * old_pg_q * qt * old_rest_q.inverse() * old_pg_q.inverse() * new_pg_q * new_rest_q);
- }
- } else if (anim->track_get_type(i) == Animation::TYPE_SCALE_3D) {
- Basis old_rest_b = old_rest.basis;
- Basis new_rest_b = new_rest.basis;
- Basis old_pg_b = old_pg.basis;
- Basis new_pg_b = new_pg.basis;
- for (int j = 0; j < key_len; j++) {
- Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j)));
- anim->track_set_key_value(i, j, (new_pg_b.inverse() * old_pg_b * sc * old_rest_b.inverse() * old_pg_b.inverse() * new_pg_b * new_rest_b).get_scale());
- }
- } else {
- Vector3 old_rest_o = old_rest.origin;
- Vector3 new_rest_o = new_rest.origin;
- Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion();
- Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion();
- for (int j = 0; j < key_len; j++) {
- Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
- anim->track_set_key_value(i, j, new_pg_q.xform_inv(old_pg_q.xform(ps - old_rest_o)) + new_rest_o);
- }
- }
- }
+ ERR_CONTINUE(!node);
+
+ Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (!track_skeleton || track_skeleton != src_skeleton) {
+ continue;
+ }
+
+ StringName bn = anim->track_get_path(i).get_subname(0);
+ if (!bn) {
+ continue;
+ }
+
+ int bone_idx = src_skeleton->find_bone(bn);
+
+ Transform3D old_rest = old_skeleton_rest[bone_idx];
+ Transform3D new_rest = src_skeleton->get_bone_rest(bone_idx);
+ Transform3D old_pg;
+ Transform3D new_pg;
+ int parent_idx = src_skeleton->get_bone_parent(bone_idx);
+ if (parent_idx >= 0) {
+ old_pg = old_skeleton_global_rest[parent_idx];
+ new_pg = src_skeleton->get_bone_global_rest(parent_idx);
+ }
+
+ int key_len = anim->track_get_key_count(i);
+ if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) {
+ Quaternion old_rest_q = old_rest.basis.get_rotation_quaternion();
+ Quaternion new_rest_q = new_rest.basis.get_rotation_quaternion();
+ Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion();
+ Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion();
+ for (int j = 0; j < key_len; j++) {
+ Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j));
+ anim->track_set_key_value(i, j, new_pg_q.inverse() * old_pg_q * qt * old_rest_q.inverse() * old_pg_q.inverse() * new_pg_q * new_rest_q);
+ }
+ } else if (anim->track_get_type(i) == Animation::TYPE_SCALE_3D) {
+ Basis old_rest_b = old_rest.basis;
+ Basis new_rest_b = new_rest.basis;
+ Basis old_pg_b = old_pg.basis;
+ Basis new_pg_b = new_pg.basis;
+ for (int j = 0; j < key_len; j++) {
+ Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j)));
+ anim->track_set_key_value(i, j, (new_pg_b.inverse() * old_pg_b * sc * old_rest_b.inverse() * old_pg_b.inverse() * new_pg_b * new_rest_b).get_scale());
+ }
+ } else {
+ Vector3 old_rest_o = old_rest.origin;
+ Vector3 new_rest_o = new_rest.origin;
+ Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion();
+ Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion();
+ for (int j = 0; j < key_len; j++) {
+ Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j));
+ anim->track_set_key_value(i, j, new_pg_q.xform_inv(old_pg_q.xform(ps - old_rest_o)) + new_rest_o);
}
}
}
@@ -595,26 +646,35 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
// Fix skin.
{
TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
+ int skin_idx = 0;
while (nodes.size()) {
ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
+ ERR_CONTINUE(!mi);
+
Ref<Skin> skin = mi->get_skin();
- if (skin.is_valid()) {
- Node *node = mi->get_node(mi->get_skeleton_path());
- if (node) {
- Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
- if (mesh_skeleton && node == src_skeleton) {
- int skin_len = skin->get_bind_count();
- for (int i = 0; i < skin_len; i++) {
- StringName bn = skin->get_bind_name(i);
- int bone_idx = src_skeleton->find_bone(bn);
- if (bone_idx >= 0) {
- Transform3D new_rest = silhouette_diff[i] * src_skeleton->get_bone_global_rest(bone_idx);
- skin->set_bind_pose(i, new_rest.inverse());
- }
- }
- }
+ ERR_CONTINUE(!skin.is_valid());
+
+ Node *node = mi->get_node(mi->get_skeleton_path());
+ ERR_CONTINUE(!node);
+
+ Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (!mesh_skeleton || mesh_skeleton != src_skeleton) {
+ continue;
+ }
+
+ Vector<Transform3D> ibm_diff = ibm_diffs[skin_idx];
+
+ int skin_len = skin->get_bind_count();
+ for (int i = 0; i < skin_len; i++) {
+ StringName bn = skin->get_bind_name(i);
+ int bone_idx = src_skeleton->find_bone(bn);
+ if (bone_idx >= 0) {
+ Transform3D new_rest = silhouette_diff[i] * src_skeleton->get_bone_global_rest(bone_idx);
+ skin->set_bind_pose(i, new_rest.inverse() * ibm_diff[bone_idx]);
}
}
+
+ skin_idx++;
}
}
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index 2809eb01cd..1a6106b4fb 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -1023,11 +1023,9 @@ void AnimationNodeStateMachineEditor::_add_menu_type(int p_index) {
}
updating = true;
- undo_redo->create_action(TTR("Add Node"));
+ undo_redo->create_action(TTR("Add Node and Transition"));
undo_redo->add_do_method(state_machine.ptr(), "add_node", name, node, add_node_pos);
undo_redo->add_undo_method(state_machine.ptr(), "remove_node", name);
- undo_redo->add_do_method(this, "_update_graph");
- undo_redo->add_undo_method(this, "_update_graph");
connecting_to_node = name;
_add_transition(true);
undo_redo->commit_action();
@@ -1051,11 +1049,9 @@ void AnimationNodeStateMachineEditor::_add_animation_type(int p_index) {
}
updating = true;
- undo_redo->create_action(TTR("Add Node"));
+ undo_redo->create_action(TTR("Add Node and Transition"));
undo_redo->add_do_method(state_machine.ptr(), "add_node", name, anim, add_node_pos);
undo_redo->add_undo_method(state_machine.ptr(), "remove_node", name);
- undo_redo->add_do_method(this, "_update_graph");
- undo_redo->add_undo_method(this, "_update_graph");
connecting_to_node = name;
_add_transition(true);
undo_redo->commit_action();
@@ -1083,16 +1079,16 @@ void AnimationNodeStateMachineEditor::_add_transition(const bool p_nested_action
if (!p_nested_action) {
updating = true;
+ undo_redo->create_action(TTR("Add Transition"));
}
- undo_redo->create_action(TTR("Add Transition"));
undo_redo->add_do_method(state_machine.ptr(), "add_transition", connecting_from, connecting_to_node, tr);
undo_redo->add_undo_method(state_machine.ptr(), "remove_transition", connecting_from, connecting_to_node);
undo_redo->add_do_method(this, "_update_graph");
undo_redo->add_undo_method(this, "_update_graph");
- undo_redo->commit_action();
if (!p_nested_action) {
+ undo_redo->commit_action();
updating = false;
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index e2265f2f83..cde4490cd3 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -1255,16 +1255,14 @@ void SceneTreeDock::_notification(int p_what) {
// create_root_dialog
HBoxContainer *top_row = memnew(HBoxContainer);
- top_row->set_name("NodeShortcutsTopRow");
top_row->set_h_size_flags(SIZE_EXPAND_FILL);
Label *l = memnew(Label(TTR("Create Root Node:")));
l->set_theme_type_variation("HeaderSmall");
top_row->add_child(l);
top_row->add_spacer();
- Button *node_shortcuts_toggle = memnew(Button);
+ node_shortcuts_toggle = memnew(Button);
node_shortcuts_toggle->set_flat(true);
- node_shortcuts_toggle->set_name("NodeShortcutsToggle");
node_shortcuts_toggle->set_icon(get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons")));
node_shortcuts_toggle->set_toggle_mode(true);
node_shortcuts_toggle->set_tooltip_text(TTR("Switch to Favorite Nodes"));
@@ -1276,18 +1274,15 @@ void SceneTreeDock::_notification(int p_what) {
create_root_dialog->add_child(top_row);
ScrollContainer *scroll_container = memnew(ScrollContainer);
- scroll_container->set_name("NodeShortcutsScrollContainer");
create_root_dialog->add_child(scroll_container);
scroll_container->set_v_size_flags(SIZE_EXPAND_FILL);
scroll_container->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
VBoxContainer *node_shortcuts = memnew(VBoxContainer);
- node_shortcuts->set_name("NodeShortcuts");
scroll_container->add_child(node_shortcuts);
node_shortcuts->set_h_size_flags(SIZE_EXPAND_FILL);
- VBoxContainer *beginner_node_shortcuts = memnew(VBoxContainer);
- beginner_node_shortcuts->set_name("BeginnerNodeShortcuts");
+ beginner_node_shortcuts = memnew(VBoxContainer);
node_shortcuts->add_child(beginner_node_shortcuts);
button_2d = memnew(Button);
@@ -1308,8 +1303,7 @@ void SceneTreeDock::_notification(int p_what) {
button_ui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons")));
button_ui->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_USER_INTERFACE, false));
- VBoxContainer *favorite_node_shortcuts = memnew(VBoxContainer);
- favorite_node_shortcuts->set_name("FavoriteNodeShortcuts");
+ favorite_node_shortcuts = memnew(VBoxContainer);
node_shortcuts->add_child(favorite_node_shortcuts);
button_custom = memnew(Button);
@@ -3227,25 +3221,11 @@ void SceneTreeDock::_local_tree_selected() {
}
void SceneTreeDock::_update_create_root_dialog() {
- BaseButton *toggle = Object::cast_to<BaseButton>(create_root_dialog->get_node(String("NodeShortcutsTopRow/NodeShortcutsToggle")));
- Node *node_shortcuts = create_root_dialog->get_node(String("NodeShortcutsScrollContainer/NodeShortcuts"));
-
- if (!toggle || !node_shortcuts) {
- return;
- }
-
- Control *beginner_nodes = Object::cast_to<Control>(node_shortcuts->get_node(String("BeginnerNodeShortcuts")));
- Control *favorite_nodes = Object::cast_to<Control>(node_shortcuts->get_node(String("FavoriteNodeShortcuts")));
-
- if (!beginner_nodes || !favorite_nodes) {
- return;
- }
-
- EditorSettings::get_singleton()->set_setting("_use_favorites_root_selection", toggle->is_pressed());
+ EditorSettings::get_singleton()->set_setting("_use_favorites_root_selection", node_shortcuts_toggle->is_pressed());
EditorSettings::get_singleton()->save();
- if (toggle->is_pressed()) {
- for (int i = 0; i < favorite_nodes->get_child_count(); i++) {
- favorite_nodes->get_child(i)->queue_delete();
+ if (node_shortcuts_toggle->is_pressed()) {
+ for (int i = 0; i < favorite_node_shortcuts->get_child_count(); i++) {
+ favorite_node_shortcuts->get_child(i)->queue_delete();
}
Ref<FileAccess> f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().path_join("favorites.Node"), FileAccess::READ);
@@ -3255,7 +3235,7 @@ void SceneTreeDock::_update_create_root_dialog() {
if (!l.is_empty()) {
Button *button = memnew(Button);
- favorite_nodes->add_child(button);
+ favorite_node_shortcuts->add_child(button);
button->set_text(l);
button->set_clip_text(true);
String name = l.get_slicec(' ', 0);
@@ -3268,14 +3248,14 @@ void SceneTreeDock::_update_create_root_dialog() {
}
}
- if (!favorite_nodes->is_visible_in_tree()) {
- favorite_nodes->show();
- beginner_nodes->hide();
+ if (!favorite_node_shortcuts->is_visible_in_tree()) {
+ favorite_node_shortcuts->show();
+ beginner_node_shortcuts->hide();
}
} else {
- if (!beginner_nodes->is_visible_in_tree()) {
- beginner_nodes->show();
- favorite_nodes->hide();
+ if (!beginner_node_shortcuts->is_visible_in_tree()) {
+ beginner_node_shortcuts->show();
+ favorite_node_shortcuts->hide();
}
button_clipboard->set_visible(!node_clipboard.is_empty());
}
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index e15865036b..dc228e1c93 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -119,6 +119,10 @@ class SceneTreeDock : public VBoxContainer {
Button *button_detach_script = nullptr;
MenuButton *button_tree_menu = nullptr;
+ Button *node_shortcuts_toggle = nullptr;
+ VBoxContainer *beginner_node_shortcuts = nullptr;
+ VBoxContainer *favorite_node_shortcuts = nullptr;
+
Button *button_2d = nullptr;
Button *button_3d = nullptr;
Button *button_ui = nullptr;