diff options
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_help.cpp | 6 | ||||
-rw-r--r-- | editor/editor_properties.cpp | 18 | ||||
-rw-r--r-- | editor/editor_sectioned_inspector.cpp | 13 | ||||
-rw-r--r-- | editor/editor_themes.cpp | 20 | ||||
-rw-r--r-- | editor/import/post_import_plugin_skeleton_renamer.cpp | 2 | ||||
-rw-r--r-- | editor/import/post_import_plugin_skeleton_rest_fixer.cpp | 348 | ||||
-rw-r--r-- | editor/plugins/skeleton_3d_editor_plugin.cpp | 5 | ||||
-rw-r--r-- | editor/scene_tree_dock.cpp | 48 | ||||
-rw-r--r-- | editor/scene_tree_dock.h | 4 |
9 files changed, 254 insertions, 210 deletions
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 97f5363bb8..de89cd8df4 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -567,6 +567,8 @@ void EditorHelp::_update_doc() { class_desc->pop(); // font class_desc->add_newline(); + const String non_breaking_space = String::chr(160); + // Inheritance tree // Ascendents @@ -579,7 +581,7 @@ void EditorHelp::_update_doc() { while (!inherits.is_empty()) { _add_type_icon(inherits); - class_desc->add_text(" "); // Extra space, otherwise icon borrows hyperlink from _add_type(). + class_desc->add_text(non_breaking_space); // Otherwise icon borrows hyperlink from _add_type(). _add_type(inherits); inherits = doc->class_list[inherits].inherits; @@ -612,7 +614,7 @@ void EditorHelp::_update_doc() { class_desc->add_text(" , "); } _add_type_icon(E.value.name); - class_desc->add_text(" "); // Extra space, otherwise icon borrows hyperlink from _add_type(). + class_desc->add_text(non_breaking_space); // Otherwise icon borrows hyperlink from _add_type(). _add_type(E.value.name); prev = true; } diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index d78fee6ad6..7364258a07 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -4182,8 +4182,8 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, const Varian } struct EditorPropertyRangeHint { - bool greater = true; - bool lesser = true; + bool or_greater = true; + bool or_less = true; double min = -99999.0; double max = 99999.0; double step = 1.0; @@ -4201,8 +4201,8 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri ERR_FAIL_COND_V_MSG(slices.size() < 2, hint, vformat("Invalid PROPERTY_HINT_RANGE with hint \"%s\": Missing required min and/or max values.", p_hint_text)); - hint.greater = false; // If using ranged, assume false by default. - hint.lesser = false; + hint.or_greater = false; // If using ranged, assume false by default. + hint.or_less = false; hint.min = slices[0].to_float(); hint.max = slices[1].to_float(); @@ -4215,9 +4215,9 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri for (int i = 2; i < slices.size(); i++) { String slice = slices[i].strip_edges(); if (slice == "or_greater") { - hint.greater = true; - } else if (slice == "or_lesser") { - hint.lesser = true; + hint.or_greater = true; + } else if (slice == "or_less") { + hint.or_less = true; } else if (slice == "no_slider") { hint.hide_slider = true; } else if (slice == "exp") { @@ -4314,7 +4314,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyInteger *editor = memnew(EditorPropertyInteger); EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); - editor->setup(hint.min, hint.max, hint.step, hint.greater, hint.lesser, hint.suffix); + editor->setup(hint.min, hint.max, hint.step, hint.or_greater, hint.or_less, hint.suffix); return editor; } @@ -4342,7 +4342,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyFloat *editor = memnew(EditorPropertyFloat); EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); - editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.exp_range, hint.greater, hint.lesser, hint.suffix, hint.radians); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.exp_range, hint.or_greater, hint.or_less, hint.suffix, hint.radians); return editor; } diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp index 94ee741db5..e078bea037 100644 --- a/editor/editor_sectioned_inspector.cpp +++ b/editor/editor_sectioned_inspector.cpp @@ -113,18 +113,13 @@ class SectionedInspectorFilter : public Object { } } - bool property_can_revert(const StringName &p_name) { + bool _property_can_revert(const StringName &p_name) const { return edited->property_can_revert(section + "/" + p_name); } - Variant property_get_revert(const StringName &p_name) { - return edited->property_get_revert(section + "/" + p_name); - } - -protected: - static void _bind_methods() { - ClassDB::bind_method("property_can_revert", &SectionedInspectorFilter::property_can_revert); - ClassDB::bind_method("property_get_revert", &SectionedInspectorFilter::property_get_revert); + bool _property_get_revert(const StringName &p_name, Variant &r_property) const { + r_property = edited->property_get_revert(section + "/" + p_name); + return true; } public: diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index d0bb63dde9..76d5daadfb 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -182,7 +182,7 @@ static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = Ref<StyleBoxFlat> style(memnew(StyleBoxFlat)); style->set_bg_color(p_color); // Adjust level of detail based on the corners' effective sizes. - style->set_corner_detail(Math::ceil(1.5 * p_corner_width * EDSCALE)); + style->set_corner_detail(Math::ceil(0.8 * p_corner_width * EDSCALE)); style->set_corner_radius_all(p_corner_width * EDSCALE); style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE); style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE); @@ -593,7 +593,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { Ref<StyleBoxFlat> style_default = make_flat_stylebox(base_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size, corner_width); style_default->set_border_width_all(border_width); style_default->set_border_color(base_color); - style_default->set_draw_center(true); // Button and widgets const float extra_spacing = EDITOR_GET("interface/theme/additional_spacing"); @@ -635,6 +634,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color shadow_color = Color(0, 0, 0, dark_theme ? 0.3 : 0.1); style_popup->set_shadow_color(shadow_color); style_popup->set_shadow_size(4 * EDSCALE); + // Popups are separate windows by default in the editor. Windows currently don't support per-pixel transparency + // in 4.0, and even if it was, it may not always work in practice (e.g. running with compositing disabled). + style_popup->set_corner_radius_all(0); Ref<StyleBoxLine> style_popup_separator(memnew(StyleBoxLine)); style_popup_separator->set_color(separator_color); @@ -661,10 +663,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_tab_base->set_border_width_all(0); // Don't round the top corners to avoid creating a small blank space between the tabs and the main panel. // This also makes the top highlight look better. - style_tab_base->set_corner_detail(corner_width); - style_tab_base->set_corner_radius_all(0); - style_tab_base->set_corner_radius(CORNER_TOP_LEFT, corner_radius * EDSCALE); - style_tab_base->set_corner_radius(CORNER_TOP_RIGHT, corner_radius * EDSCALE); + style_tab_base->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + style_tab_base->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); // Prevent visible artifacts and cover the top-left rounded corner of the panel below the tab if selected // We can't prevent them with both rounded corners and non-zero border width, though @@ -975,9 +975,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Always display a border for PopupMenus so they can be distinguished from their background. style_popup_menu->set_border_width_all(EDSCALE); style_popup_menu->set_border_color(dark_color_2); - // Popups are separate windows by default in the editor. Windows currently don't support per-pixel transparency - // in 4.0, and even if it was, it may not always work in practice (e.g. running with compositing disabled). - style_popup_menu->set_corner_radius_all(0); theme->set_stylebox("panel", "PopupMenu", style_popup_menu); Ref<StyleBoxFlat> style_menu_hover = style_widget_hover->duplicate(); @@ -1653,6 +1650,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { graphsbcomment->set_border_width(SIDE_TOP, 24 * EDSCALE); graphsbcommentselected->set_border_width(SIDE_TOP, 24 * EDSCALE); + graphsb->set_corner_detail(corner_radius * EDSCALE); + graphsbselected->set_corner_detail(corner_radius * EDSCALE); + graphsbcomment->set_corner_detail(corner_radius * EDSCALE); + graphsbcommentselected->set_corner_detail(corner_radius * EDSCALE); + theme->set_stylebox("frame", "GraphNode", graphsb); theme->set_stylebox("selected_frame", "GraphNode", graphsbselected); theme->set_stylebox("comment", "GraphNode", graphsbcomment); 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/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index c57412978d..15ae4ffcff 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -711,7 +711,6 @@ void Skeleton3DEditor::create_editors() { ne->add_control_to_menu_panel(skeleton_options); skeleton_options->set_text(TTR("Skeleton3D")); - skeleton_options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Skeleton3D"), SNAME("EditorIcons"))); // Skeleton options. PopupMenu *p = skeleton_options->get_popup(); @@ -824,7 +823,6 @@ void Skeleton3DEditor::create_editors() { void Skeleton3DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - create_editors(); update_joint_tree(); update_editors(); @@ -844,6 +842,7 @@ void Skeleton3DEditor::_notification(int p_what) { add_theme_constant_override("separation", 0); } break; case NOTIFICATION_THEME_CHANGED: { + skeleton_options->set_icon(get_theme_icon(SNAME("Skeleton3D"), SNAME("EditorIcons"))); edit_mode_button->set_icon(get_theme_icon(SNAME("ToolBoneSelect"), SNAME("EditorIcons"))); key_loc_button->set_icon(get_theme_icon(SNAME("KeyPosition"), SNAME("EditorIcons"))); key_rot_button->set_icon(get_theme_icon(SNAME("KeyRotation"), SNAME("EditorIcons"))); @@ -928,6 +927,8 @@ void fragment() { handles_mesh_instance->set_cast_shadows_setting(GeometryInstance3D::SHADOW_CASTING_SETTING_OFF); handles_mesh.instantiate(); handles_mesh_instance->set_mesh(handles_mesh); + + create_editors(); } void Skeleton3DEditor::update_bone_original() { 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; |