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

Add support for visualizing bones in Advanced Import Settings #78188

Closed
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
23 changes: 22 additions & 1 deletion editor/import/3d/scene_import_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<Skeleton3D>(p_node)) {
category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE;
skeletons.push_back(Object::cast_to<Skeleton3D>(p_node));
Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(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;
}
Expand Down Expand Up @@ -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<Skeleton3D>(p_node);
if (skeleton) {
bones_mesh_preview->set_mesh(Skeleton3DGizmoPlugin::get_bones_mesh(skeleton, -1, true));
}
}

void SceneImportSettingsDialog::_update_scene() {
Expand Down Expand Up @@ -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<Node3D>(scene)) {
Object::cast_to<Node3D>(scene)->show();
}
Expand Down Expand Up @@ -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<Skeleton3D>(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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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));
Expand Down
2 changes: 2 additions & 0 deletions editor/import/3d/scene_import_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<StandardMaterial3D> collider_mat;

Expand Down Expand Up @@ -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<InputEvent> &p_input);
Expand Down
61 changes: 36 additions & 25 deletions editor/plugins/skeleton_3d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1181,16 +1181,18 @@ int Skeleton3DEditor::get_selected_bone() const {
return selected_bone;
}

Skeleton3DGizmoPlugin::SelectionMaterials Skeleton3DGizmoPlugin::selection_materials;

Skeleton3DGizmoPlugin::Skeleton3DGizmoPlugin() {
AThousandShips marked this conversation as resolved.
Show resolved Hide resolved
unselected_mat = Ref<StandardMaterial3D>(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<ShaderMaterial>(memnew(ShaderMaterial));
selected_sh = Ref<Shader>(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<Shader> selected_sh = Ref<Shader>(memnew(Shader));
selected_sh->set_code(R"(
// Skeleton 3D gizmo bones shader.

Expand All @@ -1209,7 +1211,7 @@ void fragment() {
ALPHA = COLOR.a;
}
)");
selected_mat->set_shader(selected_sh);
selection_materials.selected_mat->set_shader(selected_sh);
jeronimo-schreyer marked this conversation as resolved.
Show resolved Hide resolved

// Register properties in editor settings.
EDITOR_DEF_RST("editors/3d_gizmos/gizmo_colors/skeleton", Color(1, 0.8, 0.4));
Expand All @@ -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<Skeleton3D>(p_spatial) != nullptr;
}
Expand Down Expand Up @@ -1355,6 +1362,11 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
selected = se->get_selected_bone();
}

Ref<ArrayMesh> m = get_bones_mesh(skeleton, selected, p_gizmo->is_selected());
p_gizmo->add_mesh(m, Ref<Material>(), Transform3D(), skeleton->register_skin(skeleton->create_skin_from_rest_transforms()));
}

Ref<ArrayMesh> 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");
Expand All @@ -1368,11 +1380,11 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Ref<SurfaceTool> 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<int> bones;
Expand All @@ -1386,16 +1398,16 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
weights[0] = 1;

int current_bone_index = 0;
Vector<int> bones_to_process = skeleton->get_parentless_bones();
Vector<int> 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<int> 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++) {
Expand All @@ -1406,16 +1418,16 @@ 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);

// Find closest axis.
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;
}
Expand All @@ -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();
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -1527,6 +1539,5 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
}

Ref<ArrayMesh> m = surface_tool->commit();
p_gizmo->add_mesh(m, Ref<Material>(), Transform3D(), skeleton->register_skin(skeleton->create_skin_from_rest_transforms()));
return surface_tool->commit();
}
11 changes: 8 additions & 3 deletions editor/plugins/skeleton_3d_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,15 @@ class Skeleton3DEditorPlugin : public EditorPlugin {
class Skeleton3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(Skeleton3DGizmoPlugin, EditorNode3DGizmoPlugin);

Ref<StandardMaterial3D> unselected_mat;
Ref<ShaderMaterial> selected_mat;
Ref<Shader> selected_sh;
struct SelectionMaterials {
Ref<StandardMaterial3D> unselected_mat;
Ref<ShaderMaterial> selected_mat;
};
static SelectionMaterials selection_materials;

public:
static Ref<ArrayMesh> 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;
Expand All @@ -269,6 +273,7 @@ class Skeleton3DGizmoPlugin : public EditorNode3DGizmoPlugin {
void redraw(EditorNode3DGizmo *p_gizmo) override;

Skeleton3DGizmoPlugin();
~Skeleton3DGizmoPlugin();
};

#endif // SKELETON_3D_EDITOR_PLUGIN_H
Loading