diff --git a/editor/import/3d/scene_import_settings.cpp b/editor/import/3d/scene_import_settings.cpp index 67b13e33288b..80989ea7a3bd 100644 --- a/editor/import/3d/scene_import_settings.cpp +++ b/editor/import/3d/scene_import_settings.cpp @@ -37,6 +37,7 @@ #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/plugins/skeleton_3d_editor_plugin.h" #include "editor/themes/editor_scale.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/animation/animation_player.h" @@ -414,7 +415,9 @@ void SceneImportSettingsDialog::_fill_scene(Node *p_node, TreeItem *p_parent_ite animation_player->connect(SNAME("animation_finished"), callable_mp(this, &SceneImportSettingsDialog::_animation_finished)); } else if (Object::cast_to(p_node)) { category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE; - skeletons.push_back(Object::cast_to(p_node)); + Skeleton3D *skeleton = Object::cast_to(p_node); + skeleton->connect(SNAME("tree_entered"), callable_mp(this, &SceneImportSettingsDialog::_skeleton_tree_entered).bind(skeleton)); + skeletons.push_back(skeleton); } else { category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE; } @@ -474,6 +477,11 @@ void SceneImportSettingsDialog::_fill_scene(Node *p_node, TreeItem *p_parent_ite contents_aabb.merge_with(aabb); } } + + Skeleton3D *skeleton = Object::cast_to(p_node); + if (skeleton) { + bones_mesh_preview->set_mesh(Skeleton3DGizmoPlugin::get_bones_mesh(skeleton, -1, true)); + } } void SceneImportSettingsDialog::_update_scene() { @@ -794,6 +802,7 @@ void SceneImportSettingsDialog::_select(Tree *p_from, const String &p_type, cons mesh_preview->hide(); _reset_animation(); + bones_mesh_preview->hide(); if (Object::cast_to(scene)) { Object::cast_to(scene)->show(); } @@ -828,6 +837,7 @@ void SceneImportSettingsDialog::_select(Tree *p_from, const String &p_type, cons scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE; } else if (Object::cast_to(nd.node)) { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE; + bones_mesh_preview->show(); } else { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE; scene_import_settings_data->hide_options = editing_animation; @@ -1049,6 +1059,10 @@ void SceneImportSettingsDialog::_animation_slider_value_changed(double p_value) animation_player->seek(p_value * animation_map[selected_id].animation->get_length(), true); } +void SceneImportSettingsDialog::_skeleton_tree_entered(Skeleton3D *skeleton) { + bones_mesh_preview->set_skeleton_path(skeleton->get_path()); +} + void SceneImportSettingsDialog::_animation_finished(const StringName &p_name) { Animation::LoopMode loop_mode = animation_loop_mode; @@ -1708,6 +1722,13 @@ SceneImportSettingsDialog::SceneImportSettingsDialog() { collider_mat->set_albedo(Color(0.5, 0.5, 1.0)); } + { + bones_mesh_preview = memnew(MeshInstance3D); + bones_mesh_preview->set_cast_shadows_setting(GeometryInstance3D::SHADOW_CASTING_SETTING_OFF); + bones_mesh_preview->set_skeleton_path(NodePath()); + base_viewport->add_child(bones_mesh_preview); + } + inspector = memnew(EditorInspector); inspector->set_custom_minimum_size(Size2(300 * EDSCALE, 0)); inspector->connect(SNAME("property_edited"), callable_mp(this, &SceneImportSettingsDialog::_inspector_property_edited)); diff --git a/editor/import/3d/scene_import_settings.h b/editor/import/3d/scene_import_settings.h index f4954c41db1d..d2794830ee5d 100644 --- a/editor/import/3d/scene_import_settings.h +++ b/editor/import/3d/scene_import_settings.h @@ -98,6 +98,7 @@ class SceneImportSettingsDialog : public ConfirmationDialog { bool animation_pingpong = false; bool previous_import_as_skeleton = false; bool previous_rest_as_reset = false; + MeshInstance3D *bones_mesh_preview = nullptr; Ref collider_mat; @@ -175,6 +176,7 @@ class SceneImportSettingsDialog : public ConfirmationDialog { void _material_tree_selected(); void _mesh_tree_selected(); void _scene_tree_selected(); + void _skeleton_tree_entered(Skeleton3D *skeleton); void _cleanup(); void _viewport_input(const Ref &p_input); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 1bd6b4e5b1ae..7c50ba40b5c6 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -1181,16 +1181,18 @@ int Skeleton3DEditor::get_selected_bone() const { return selected_bone; } +Skeleton3DGizmoPlugin::SelectionMaterials Skeleton3DGizmoPlugin::selection_materials; + Skeleton3DGizmoPlugin::Skeleton3DGizmoPlugin() { - unselected_mat = Ref(memnew(StandardMaterial3D)); - unselected_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); - unselected_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); - unselected_mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - unselected_mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); - unselected_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); - - selected_mat = Ref(memnew(ShaderMaterial)); - selected_sh = Ref(memnew(Shader)); + selection_materials.unselected_mat.instantiate(); + selection_materials.unselected_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + selection_materials.unselected_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + selection_materials.unselected_mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + selection_materials.unselected_mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); + selection_materials.unselected_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); + + selection_materials.selected_mat.instantiate(); + Ref selected_sh = Ref(memnew(Shader)); selected_sh->set_code(R"( // Skeleton 3D gizmo bones shader. @@ -1209,7 +1211,7 @@ void fragment() { ALPHA = COLOR.a; } )"); - selected_mat->set_shader(selected_sh); + selection_materials.selected_mat->set_shader(selected_sh); // Register properties in editor settings. EDITOR_DEF_RST("editors/3d_gizmos/gizmo_colors/skeleton", Color(1, 0.8, 0.4)); @@ -1219,6 +1221,11 @@ void fragment() { EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "editors/3d_gizmos/gizmo_settings/bone_shape", PROPERTY_HINT_ENUM, "Wire,Octahedron")); } +Skeleton3DGizmoPlugin::~Skeleton3DGizmoPlugin() { + selection_materials.unselected_mat.unref(); + selection_materials.selected_mat.unref(); +} + bool Skeleton3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } @@ -1355,6 +1362,11 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { selected = se->get_selected_bone(); } + Ref m = get_bones_mesh(skeleton, selected, p_gizmo->is_selected()); + p_gizmo->add_mesh(m, Ref(), Transform3D(), skeleton->register_skin(skeleton->create_skin_from_rest_transforms())); +} + +Ref Skeleton3DGizmoPlugin::get_bones_mesh(Skeleton3D *p_skeleton, int p_selected, bool p_is_selected) { Color bone_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/skeleton"); Color selected_bone_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/selected_bone"); real_t bone_axis_length = EDITOR_GET("editors/3d_gizmos/gizmo_settings/bone_axis_length"); @@ -1368,11 +1380,11 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Ref surface_tool(memnew(SurfaceTool)); surface_tool->begin(Mesh::PRIMITIVE_LINES); - if (p_gizmo->is_selected()) { - surface_tool->set_material(selected_mat); + if (p_is_selected) { + surface_tool->set_material(selection_materials.selected_mat); } else { - unselected_mat->set_albedo(bone_color); - surface_tool->set_material(unselected_mat); + selection_materials.unselected_mat->set_albedo(bone_color); + surface_tool->set_material(selection_materials.unselected_mat); } LocalVector bones; @@ -1386,16 +1398,16 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { weights[0] = 1; int current_bone_index = 0; - Vector bones_to_process = skeleton->get_parentless_bones(); + Vector bones_to_process = p_skeleton->get_parentless_bones(); while (bones_to_process.size() > current_bone_index) { int current_bone_idx = bones_to_process[current_bone_index]; current_bone_index++; - Color current_bone_color = (current_bone_idx == selected) ? selected_bone_color : bone_color; + Color current_bone_color = (current_bone_idx == p_selected) ? selected_bone_color : bone_color; Vector child_bones_vector; - child_bones_vector = skeleton->get_bone_children(current_bone_idx); + child_bones_vector = p_skeleton->get_bone_children(current_bone_idx); int child_bones_size = child_bones_vector.size(); for (int i = 0; i < child_bones_size; i++) { @@ -1406,8 +1418,8 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { int child_bone_idx = child_bones_vector[i]; - Vector3 v0 = skeleton->get_bone_global_rest(current_bone_idx).origin; - Vector3 v1 = skeleton->get_bone_global_rest(child_bone_idx).origin; + Vector3 v0 = p_skeleton->get_bone_global_rest(current_bone_idx).origin; + Vector3 v1 = p_skeleton->get_bone_global_rest(child_bone_idx).origin; Vector3 d = (v1 - v0).normalized(); real_t dist = v0.distance_to(v1); @@ -1415,7 +1427,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { int closest = -1; real_t closest_d = 0.0; for (int j = 0; j < 3; j++) { - real_t dp = Math::abs(skeleton->get_bone_global_rest(current_bone_idx).basis[j].normalized().dot(d)); + real_t dp = Math::abs(p_skeleton->get_bone_global_rest(current_bone_idx).basis[j].normalized().dot(d)); if (j == 0 || dp > closest_d) { closest = j; } @@ -1442,7 +1454,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { for (int j = 0; j < 3; j++) { Vector3 axis; if (first == Vector3()) { - axis = d.cross(d.cross(skeleton->get_bone_global_rest(current_bone_idx).basis[j])).normalized(); + axis = d.cross(d.cross(p_skeleton->get_bone_global_rest(current_bone_idx).basis[j])).normalized(); first = axis; } else { axis = d.cross(first).normalized(); @@ -1497,7 +1509,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { surface_tool->add_vertex(v0); surface_tool->set_bones(bones); surface_tool->set_weights(weights); - surface_tool->add_vertex(v0 + (skeleton->get_bone_global_rest(current_bone_idx).basis.inverse())[j].normalized() * dist * bone_axis_length); + surface_tool->add_vertex(v0 + (p_skeleton->get_bone_global_rest(current_bone_idx).basis.inverse())[j].normalized() * dist * bone_axis_length); if (j == closest) { continue; @@ -1514,7 +1526,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { surface_tool->add_vertex(v1); surface_tool->set_bones(bones); surface_tool->set_weights(weights); - surface_tool->add_vertex(v1 + (skeleton->get_bone_global_rest(child_bone_idx).basis.inverse())[j].normalized() * dist * bone_axis_length); + surface_tool->add_vertex(v1 + (p_skeleton->get_bone_global_rest(child_bone_idx).basis.inverse())[j].normalized() * dist * bone_axis_length); if (j == closest) { continue; @@ -1527,6 +1539,5 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } } - Ref m = surface_tool->commit(); - p_gizmo->add_mesh(m, Ref(), Transform3D(), skeleton->register_skin(skeleton->create_skin_from_rest_transforms())); + return surface_tool->commit(); } diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h index f62d017c4018..5857f524e8d4 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.h +++ b/editor/plugins/skeleton_3d_editor_plugin.h @@ -252,11 +252,15 @@ class Skeleton3DEditorPlugin : public EditorPlugin { class Skeleton3DGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(Skeleton3DGizmoPlugin, EditorNode3DGizmoPlugin); - Ref unselected_mat; - Ref selected_mat; - Ref selected_sh; + struct SelectionMaterials { + Ref unselected_mat; + Ref selected_mat; + }; + static SelectionMaterials selection_materials; public: + static Ref get_bones_mesh(Skeleton3D *p_skeleton, int p_selected, bool p_is_selected); + bool has_gizmo(Node3D *p_spatial) override; String get_gizmo_name() const override; int get_priority() const override; @@ -269,6 +273,7 @@ class Skeleton3DGizmoPlugin : public EditorNode3DGizmoPlugin { void redraw(EditorNode3DGizmo *p_gizmo) override; Skeleton3DGizmoPlugin(); + ~Skeleton3DGizmoPlugin(); }; #endif // SKELETON_3D_EDITOR_PLUGIN_H