Various improvements to advanced importer skeleton preview.

Better size calculation in advanced importer preview.
Uses the skeleton mesh to calculate the scene's bounding box.
This improves some situations where a mesh instances' scale
does not match its visual representation when a skeleton
is applied.

Advanced importer skeletal preview UX improvement.
Make the visibility of the skeletal preview in the advanced importer
when selecting an animation dependent on a new dedicated toggle button
rather than carrying over whether a skeletal node was or was not previously
selected before selecting the animation.

Advanced importer skeletal preview fix.
Fixes the preview on scaled skeletons in the advanced importer by applying the node's scale
to the preview and generating a skin for it.
This commit is contained in:
Saracen 2024-08-25 20:47:14 +01:00
parent 030fd71da2
commit 6532eff7a7
2 changed files with 51 additions and 6 deletions

View file

@ -421,7 +421,7 @@ void SceneImportSettingsDialog::_fill_scene(Node *p_node, TreeItem *p_parent_ite
} else if (Object::cast_to<Skeleton3D>(p_node)) {
category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE;
Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_node);
skeleton->connect(SNAME("tree_entered"), callable_mp(this, &SceneImportSettingsDialog::_skeleton_tree_entered).bind(skeleton));
skeleton->connect(SceneStringName(tree_entered), callable_mp(this, &SceneImportSettingsDialog::_skeleton_tree_entered).bind(skeleton));
skeletons.push_back(skeleton);
} else {
category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE;
@ -486,7 +486,27 @@ void SceneImportSettingsDialog::_fill_scene(Node *p_node, TreeItem *p_parent_ite
Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_node);
if (skeleton) {
bones_mesh_preview->set_mesh(Skeleton3DGizmoPlugin::get_bones_mesh(skeleton, -1, true));
Ref<ArrayMesh> bones_mesh = Skeleton3DGizmoPlugin::get_bones_mesh(skeleton, -1, true);
bones_mesh_preview->set_mesh(bones_mesh);
Transform3D accum_xform;
Node3D *base = skeleton;
while (base) {
accum_xform = base->get_transform() * accum_xform;
base = Object::cast_to<Node3D>(base->get_parent());
}
bones_mesh_preview->set_transform(accum_xform * skeleton->get_transform());
AABB aabb = accum_xform.xform(bones_mesh->get_aabb());
if (first_aabb) {
contents_aabb = aabb;
first_aabb = false;
} else {
contents_aabb.merge_with(aabb);
}
}
}
@ -803,12 +823,12 @@ void SceneImportSettingsDialog::_select(Tree *p_from, const String &p_type, cons
selecting = true;
scene_import_settings_data->hide_options = false;
bones_mesh_preview->hide();
if (p_type == "Node") {
node_selected->hide(); // Always hide just in case.
mesh_preview->hide();
_reset_animation();
bones_mesh_preview->hide();
if (Object::cast_to<Node3D>(scene)) {
Object::cast_to<Node3D>(scene)->show();
}
@ -863,6 +883,8 @@ void SceneImportSettingsDialog::_select(Tree *p_from, const String &p_type, cons
scene_import_settings_data->settings = &ad.settings;
scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION;
_animation_update_skeleton_visibility();
} else if (p_type == "Mesh") {
node_selected->hide();
if (Object::cast_to<Node3D>(scene)) {
@ -1065,8 +1087,9 @@ 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::_skeleton_tree_entered(Skeleton3D *p_skeleton) {
bones_mesh_preview->set_skeleton_path(p_skeleton->get_path());
bones_mesh_preview->set_skin(p_skeleton->register_skin(p_skeleton->create_skin_from_rest_transforms()));
}
void SceneImportSettingsDialog::_animation_finished(const StringName &p_name) {
@ -1094,6 +1117,14 @@ void SceneImportSettingsDialog::_animation_finished(const StringName &p_name) {
}
}
void SceneImportSettingsDialog::_animation_update_skeleton_visibility() {
if (animation_toggle_skeleton_visibility->is_pressed()) {
bones_mesh_preview->show();
} else {
bones_mesh_preview->hide();
}
}
void SceneImportSettingsDialog::_material_tree_selected() {
if (selecting) {
return;
@ -1296,6 +1327,8 @@ void SceneImportSettingsDialog::_notification(int p_what) {
light_1_switch->set_icon(theme_cache.light_1_icon);
light_2_switch->set_icon(theme_cache.light_2_icon);
light_rotate_switch->set_icon(theme_cache.rotate_icon);
animation_toggle_skeleton_visibility->set_icon(get_editor_theme_icon(SNAME("Skeleton3D")));
} break;
case NOTIFICATION_PROCESS: {
@ -1675,6 +1708,7 @@ SceneImportSettingsDialog::SceneImportSettingsDialog() {
animation_hbox->add_child(animation_stop_button);
animation_stop_button->set_flat(true);
animation_stop_button->set_focus_mode(Control::FOCUS_NONE);
animation_stop_button->set_tooltip_text(TTR("Selected Animation Stop"));
animation_stop_button->connect(SceneStringName(pressed), callable_mp(this, &SceneImportSettingsDialog::_stop_current_animation));
animation_slider = memnew(HSlider);
@ -1687,6 +1721,15 @@ SceneImportSettingsDialog::SceneImportSettingsDialog() {
animation_slider->set_focus_mode(Control::FOCUS_NONE);
animation_slider->connect(SceneStringName(value_changed), callable_mp(this, &SceneImportSettingsDialog::_animation_slider_value_changed));
animation_toggle_skeleton_visibility = memnew(Button);
animation_hbox->add_child(animation_toggle_skeleton_visibility);
animation_toggle_skeleton_visibility->set_toggle_mode(true);
animation_toggle_skeleton_visibility->set_flat(true);
animation_toggle_skeleton_visibility->set_focus_mode(Control::FOCUS_NONE);
animation_toggle_skeleton_visibility->set_tooltip_text(TTR("Toggle Animation Skeleton Visibility"));
animation_toggle_skeleton_visibility->connect(SceneStringName(pressed), callable_mp(this, &SceneImportSettingsDialog::_animation_update_skeleton_visibility));
base_viewport->set_use_own_world_3d(true);
HBoxContainer *viewport_hbox = memnew(HBoxContainer);

View file

@ -109,6 +109,7 @@ class SceneImportSettingsDialog : public ConfirmationDialog {
HSlider *animation_slider = nullptr;
Button *animation_play_button = nullptr;
Button *animation_stop_button = nullptr;
Button *animation_toggle_skeleton_visibility = nullptr;
Animation::LoopMode animation_loop_mode = Animation::LOOP_NONE;
bool animation_pingpong = false;
bool previous_import_as_skeleton = false;
@ -188,10 +189,11 @@ class SceneImportSettingsDialog : public ConfirmationDialog {
void _reset_animation(const String &p_animation_name = "");
void _animation_slider_value_changed(double p_value);
void _animation_finished(const StringName &p_name);
void _animation_update_skeleton_visibility();
void _material_tree_selected();
void _mesh_tree_selected();
void _scene_tree_selected();
void _skeleton_tree_entered(Skeleton3D *skeleton);
void _skeleton_tree_entered(Skeleton3D *p_skeleton);
void _cleanup();
void _on_light_1_switch_pressed();
void _on_light_2_switch_pressed();