2021-03-19 13:57:52 +01:00
/**************************************************************************/
/* scene_import_settings.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
# include "scene_import_settings.h"
2022-02-12 02:46:22 +01:00
2022-08-01 01:20:24 +02:00
# include "core/config/project_settings.h"
2022-02-12 02:46:22 +01:00
# include "editor/editor_file_system.h"
# include "editor/editor_inspector.h"
2021-03-19 13:57:52 +01:00
# include "editor/editor_node.h"
2022-07-31 20:14:15 +02:00
# include "editor/editor_settings.h"
2023-08-13 02:33:39 +02:00
# include "editor/editor_string_names.h"
2023-04-07 18:59:49 +02:00
# include "editor/gui/editor_file_dialog.h"
2024-01-15 13:14:55 +01:00
# include "editor/themes/editor_scale.h"
2021-09-21 03:24:31 +02:00
# include "scene/3d/importer_mesh_instance_3d.h"
2022-02-12 02:46:22 +01:00
# include "scene/animation/animation_player.h"
2021-08-13 18:42:45 +02:00
# include "scene/resources/3d/importer_mesh.h"
2021-03-19 13:57:52 +01:00
# include "scene/resources/surface_tool.h"
class SceneImportSettingsData : public Object {
GDCLASS ( SceneImportSettingsData , Object )
2023-10-06 09:00:36 +02:00
friend class SceneImportSettingsDialog ;
2022-05-13 15:04:37 +02:00
HashMap < StringName , Variant > * settings = nullptr ;
HashMap < StringName , Variant > current ;
HashMap < StringName , Variant > defaults ;
2021-03-19 13:57:52 +01:00
List < ResourceImporter : : ImportOption > options ;
2022-04-12 16:07:09 +02:00
bool hide_options = false ;
String path ;
2021-03-19 13:57:52 +01:00
ResourceImporterScene : : InternalImportCategory category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MAX ;
bool _set ( const StringName & p_name , const Variant & p_value ) {
if ( settings ) {
if ( defaults . has ( p_name ) & & defaults [ p_name ] = = p_value ) {
settings - > erase ( p_name ) ;
} else {
( * settings ) [ p_name ] = p_value ;
}
current [ p_name ] = p_value ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
2023-04-23 13:53:45 +02:00
// SceneImportSettings must decide if a new collider should be generated or not.
2023-01-19 20:34:05 +01:00
if ( category = = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE ) {
2023-10-06 09:00:36 +02:00
SceneImportSettingsDialog : : get_singleton ( ) - > request_generate_collider ( ) ;
2023-01-19 20:34:05 +01:00
}
2023-10-06 09:00:36 +02:00
if ( SceneImportSettingsDialog : : get_singleton ( ) - > is_editing_animation ( ) ) {
2022-04-12 16:07:09 +02:00
if ( category = = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MAX ) {
if ( ResourceImporterScene : : get_animation_singleton ( ) - > get_option_visibility ( path , p_name , current ) ) {
2023-10-06 09:00:36 +02:00
SceneImportSettingsDialog : : get_singleton ( ) - > update_view ( ) ;
2022-04-12 16:07:09 +02:00
}
} else {
if ( ResourceImporterScene : : get_animation_singleton ( ) - > get_internal_option_update_view_required ( category , p_name , current ) ) {
2023-10-06 09:00:36 +02:00
SceneImportSettingsDialog : : get_singleton ( ) - > update_view ( ) ;
2022-04-12 16:07:09 +02:00
}
}
} else {
if ( category = = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MAX ) {
if ( ResourceImporterScene : : get_scene_singleton ( ) - > get_option_visibility ( path , p_name , current ) ) {
2023-10-06 09:00:36 +02:00
SceneImportSettingsDialog : : get_singleton ( ) - > update_view ( ) ;
2022-04-12 16:07:09 +02:00
}
} else {
if ( ResourceImporterScene : : get_scene_singleton ( ) - > get_internal_option_update_view_required ( category , p_name , current ) ) {
2023-10-06 09:00:36 +02:00
SceneImportSettingsDialog : : get_singleton ( ) - > update_view ( ) ;
2022-04-12 16:07:09 +02:00
}
}
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
}
2021-03-19 13:57:52 +01:00
return true ;
}
return false ;
}
bool _get ( const StringName & p_name , Variant & r_ret ) const {
if ( settings ) {
if ( settings - > has ( p_name ) ) {
r_ret = ( * settings ) [ p_name ] ;
return true ;
}
}
if ( defaults . has ( p_name ) ) {
r_ret = defaults [ p_name ] ;
return true ;
}
return false ;
}
void _get_property_list ( List < PropertyInfo > * p_list ) const {
2022-04-12 16:07:09 +02:00
if ( hide_options ) {
return ;
}
2021-07-16 05:45:57 +02:00
for ( const ResourceImporter : : ImportOption & E : options ) {
2023-10-06 09:00:36 +02:00
if ( SceneImportSettingsDialog : : get_singleton ( ) - > is_editing_animation ( ) ) {
2022-04-12 16:07:09 +02:00
if ( category = = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MAX ) {
if ( ResourceImporterScene : : get_animation_singleton ( ) - > get_option_visibility ( path , E . option . name , current ) ) {
p_list - > push_back ( E . option ) ;
}
} else {
if ( ResourceImporterScene : : get_animation_singleton ( ) - > get_internal_option_visibility ( category , E . option . name , current ) ) {
p_list - > push_back ( E . option ) ;
}
}
} else {
if ( category = = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MAX ) {
if ( ResourceImporterScene : : get_scene_singleton ( ) - > get_option_visibility ( path , E . option . name , current ) ) {
p_list - > push_back ( E . option ) ;
}
} else {
if ( ResourceImporterScene : : get_scene_singleton ( ) - > get_internal_option_visibility ( category , E . option . name , current ) ) {
p_list - > push_back ( E . option ) ;
}
}
2021-03-19 13:57:52 +01:00
}
}
}
} ;
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _fill_material ( Tree * p_tree , const Ref < Material > & p_material , TreeItem * p_parent ) {
2021-03-19 13:57:52 +01:00
String import_id ;
bool has_import_id = false ;
if ( p_material - > has_meta ( " import_id " ) ) {
import_id = p_material - > get_meta ( " import_id " ) ;
has_import_id = true ;
2021-12-09 10:42:46 +01:00
} else if ( ! p_material - > get_name ( ) . is_empty ( ) ) {
2021-03-19 13:57:52 +01:00
import_id = p_material - > get_name ( ) ;
has_import_id = true ;
2022-12-09 17:01:40 +01:00
} else if ( unnamed_material_name_map . has ( p_material ) ) {
import_id = unnamed_material_name_map [ p_material ] ;
2021-03-19 13:57:52 +01:00
} else {
2022-12-09 17:01:40 +01:00
import_id = " @MATERIAL: " + itos ( material_map . size ( ) ) ;
unnamed_material_name_map [ p_material ] = import_id ;
2021-03-19 13:57:52 +01:00
}
2022-12-09 17:01:40 +01:00
bool created = false ;
2021-03-19 13:57:52 +01:00
if ( ! material_map . has ( import_id ) ) {
MaterialData md ;
2022-12-09 17:01:40 +01:00
created = true ;
2021-03-19 13:57:52 +01:00
md . has_import_id = has_import_id ;
md . material = p_material ;
_load_default_subresource_settings ( md . settings , " materials " , import_id , ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MATERIAL ) ;
material_map [ import_id ] = md ;
}
MaterialData & material_data = material_map [ import_id ] ;
2022-12-09 17:01:40 +01:00
ERR_FAIL_COND ( p_material ! = material_data . material ) ;
2021-03-19 13:57:52 +01:00
2023-08-13 02:33:39 +02:00
Ref < Texture2D > icon = get_editor_theme_icon ( SNAME ( " StandardMaterial3D " ) ) ;
2021-03-19 13:57:52 +01:00
TreeItem * item = p_tree - > create_item ( p_parent ) ;
2022-04-03 14:01:38 +02:00
if ( p_material - > get_name ( ) . is_empty ( ) ) {
item - > set_text ( 0 , TTR ( " <Unnamed Material> " ) ) ;
} else {
item - > set_text ( 0 , p_material - > get_name ( ) ) ;
2021-03-19 13:57:52 +01:00
}
2022-04-03 14:01:38 +02:00
item - > set_icon ( 0 , icon ) ;
2021-03-19 13:57:52 +01:00
item - > set_meta ( " type " , " Material " ) ;
item - > set_meta ( " import_id " , import_id ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 0 , vformat ( TTR ( " Import ID: %s " ) , import_id ) ) ;
2021-03-19 13:57:52 +01:00
item - > set_selectable ( 0 , true ) ;
if ( p_tree = = scene_tree ) {
material_data . scene_node = item ;
} else if ( p_tree = = mesh_tree ) {
material_data . mesh_node = item ;
} else {
material_data . material_node = item ;
}
if ( created ) {
_fill_material ( material_tree , p_material , material_tree - > get_root ( ) ) ;
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _fill_mesh ( Tree * p_tree , const Ref < Mesh > & p_mesh , TreeItem * p_parent ) {
2021-03-19 13:57:52 +01:00
String import_id ;
bool has_import_id = false ;
if ( p_mesh - > has_meta ( " import_id " ) ) {
import_id = p_mesh - > get_meta ( " import_id " ) ;
has_import_id = true ;
2021-12-09 10:42:46 +01:00
} else if ( ! p_mesh - > get_name ( ) . is_empty ( ) ) {
2021-03-19 13:57:52 +01:00
import_id = p_mesh - > get_name ( ) ;
has_import_id = true ;
} else {
import_id = " @MESH: " + itos ( mesh_set . size ( ) ) ;
}
if ( ! mesh_map . has ( import_id ) ) {
MeshData md ;
md . has_import_id = has_import_id ;
md . mesh = p_mesh ;
_load_default_subresource_settings ( md . settings , " meshes " , import_id , ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MESH ) ;
mesh_map [ import_id ] = md ;
}
MeshData & mesh_data = mesh_map [ import_id ] ;
2023-09-25 14:52:58 +02:00
Ref < Texture2D > icon = get_editor_theme_icon ( SNAME ( " MeshItem " ) ) ;
2021-03-19 13:57:52 +01:00
TreeItem * item = p_tree - > create_item ( p_parent ) ;
item - > set_text ( 0 , p_mesh - > get_name ( ) ) ;
item - > set_icon ( 0 , icon ) ;
bool created = false ;
if ( ! mesh_set . has ( p_mesh ) ) {
mesh_set . insert ( p_mesh ) ;
created = true ;
}
item - > set_meta ( " type " , " Mesh " ) ;
item - > set_meta ( " import_id " , import_id ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 0 , vformat ( TTR ( " Import ID: %s " ) , import_id ) ) ;
2021-03-19 13:57:52 +01:00
item - > set_selectable ( 0 , true ) ;
if ( p_tree = = scene_tree ) {
mesh_data . scene_node = item ;
} else {
mesh_data . mesh_node = item ;
}
item - > set_collapsed ( true ) ;
for ( int i = 0 ; i < p_mesh - > get_surface_count ( ) ; i + + ) {
Ref < Material > mat = p_mesh - > surface_get_material ( i ) ;
if ( mat . is_valid ( ) ) {
_fill_material ( p_tree , mat , item ) ;
}
}
if ( created ) {
_fill_mesh ( mesh_tree , p_mesh , mesh_tree - > get_root ( ) ) ;
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _fill_animation ( Tree * p_tree , const Ref < Animation > & p_anim , const String & p_name , TreeItem * p_parent ) {
2021-03-19 13:57:52 +01:00
if ( ! animation_map . has ( p_name ) ) {
AnimationData ad ;
ad . animation = p_anim ;
_load_default_subresource_settings ( ad . settings , " animations " , p_name , ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_ANIMATION ) ;
animation_map [ p_name ] = ad ;
}
AnimationData & animation_data = animation_map [ p_name ] ;
2023-08-13 02:33:39 +02:00
Ref < Texture2D > icon = get_editor_theme_icon ( SNAME ( " Animation " ) ) ;
2021-03-19 13:57:52 +01:00
TreeItem * item = p_tree - > create_item ( p_parent ) ;
item - > set_text ( 0 , p_name ) ;
item - > set_icon ( 0 , icon ) ;
item - > set_meta ( " type " , " Animation " ) ;
item - > set_meta ( " import_id " , p_name ) ;
item - > set_selectable ( 0 , true ) ;
animation_data . scene_node = item ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _fill_scene ( Node * p_node , TreeItem * p_parent_item ) {
2021-03-19 13:57:52 +01:00
String import_id ;
if ( p_node - > has_meta ( " import_id " ) ) {
import_id = p_node - > get_meta ( " import_id " ) ;
} else {
import_id = " PATH: " + String ( scene - > get_path_to ( p_node ) ) ;
p_node - > set_meta ( " import_id " , import_id ) ;
}
2021-09-21 03:24:31 +02:00
ImporterMeshInstance3D * src_mesh_node = Object : : cast_to < ImporterMeshInstance3D > ( p_node ) ;
2021-03-19 13:57:52 +01:00
if ( src_mesh_node ) {
MeshInstance3D * mesh_node = memnew ( MeshInstance3D ) ;
mesh_node - > set_name ( src_mesh_node - > get_name ( ) ) ;
mesh_node - > set_transform ( src_mesh_node - > get_transform ( ) ) ;
mesh_node - > set_skin ( src_mesh_node - > get_skin ( ) ) ;
mesh_node - > set_skeleton_path ( src_mesh_node - > get_skeleton_path ( ) ) ;
if ( src_mesh_node - > get_mesh ( ) . is_valid ( ) ) {
2021-09-21 03:24:31 +02:00
Ref < ImporterMesh > editor_mesh = src_mesh_node - > get_mesh ( ) ;
2021-03-19 13:57:52 +01:00
mesh_node - > set_mesh ( editor_mesh - > get_mesh ( ) ) ;
}
2024-01-31 13:23:26 +01:00
// Replace the original mesh node in the scene tree with the new one.
if ( unlikely ( p_node = = scene ) ) {
scene = mesh_node ;
}
2021-03-19 13:57:52 +01:00
p_node - > replace_by ( mesh_node ) ;
memdelete ( p_node ) ;
p_node = mesh_node ;
}
String type = p_node - > get_class ( ) ;
2023-08-13 02:33:39 +02:00
if ( ! has_theme_icon ( type , EditorStringName ( EditorIcons ) ) ) {
2021-03-19 13:57:52 +01:00
type = " Node3D " ;
}
2023-08-13 02:33:39 +02:00
Ref < Texture2D > icon = get_editor_theme_icon ( type ) ;
2021-03-19 13:57:52 +01:00
TreeItem * item = scene_tree - > create_item ( p_parent_item ) ;
item - > set_text ( 0 , p_node - > get_name ( ) ) ;
if ( p_node = = scene ) {
2023-08-13 02:33:39 +02:00
icon = get_editor_theme_icon ( SNAME ( " PackedScene " ) ) ;
2023-03-27 12:06:07 +02:00
item - > set_text ( 0 , TTR ( " Scene " ) ) ;
2021-03-19 13:57:52 +01:00
}
item - > set_icon ( 0 , icon ) ;
item - > set_meta ( " type " , " Node " ) ;
item - > set_meta ( " class " , type ) ;
item - > set_meta ( " import_id " , import_id ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 0 , vformat ( TTR ( " Type: %s \n Import ID: %s " ) , type , import_id ) ) ;
2021-03-19 13:57:52 +01:00
item - > set_selectable ( 0 , true ) ;
if ( ! node_map . has ( import_id ) ) {
NodeData nd ;
if ( p_node ! = scene ) {
ResourceImporterScene : : InternalImportCategory category ;
if ( src_mesh_node ) {
category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE ;
} else if ( Object : : cast_to < AnimationPlayer > ( p_node ) ) {
category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE ;
2023-04-23 13:53:45 +02:00
animation_player = Object : : cast_to < AnimationPlayer > ( p_node ) ;
2023-10-06 09:00:36 +02:00
animation_player - > connect ( SNAME ( " animation_finished " ) , callable_mp ( this , & SceneImportSettingsDialog : : _animation_finished ) ) ;
2022-06-27 10:06:50 +02:00
} else if ( Object : : cast_to < Skeleton3D > ( p_node ) ) {
category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE ;
2023-04-23 13:53:45 +02:00
skeletons . push_back ( Object : : cast_to < Skeleton3D > ( p_node ) ) ;
2021-03-19 13:57:52 +01:00
} else {
category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_NODE ;
}
_load_default_subresource_settings ( nd . settings , " nodes " , import_id , category ) ;
}
node_map [ import_id ] = nd ;
}
NodeData & node_data = node_map [ import_id ] ;
node_data . node = p_node ;
node_data . scene_node = item ;
AnimationPlayer * anim_node = Object : : cast_to < AnimationPlayer > ( p_node ) ;
if ( anim_node ) {
List < StringName > animations ;
anim_node - > get_animation_list ( & animations ) ;
2021-07-24 15:46:25 +02:00
for ( const StringName & E : animations ) {
2021-07-16 05:45:57 +02:00
_fill_animation ( scene_tree , anim_node - > get_animation ( E ) , E , item ) ;
2021-03-19 13:57:52 +01:00
}
}
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
_fill_scene ( p_node - > get_child ( i ) , item ) ;
}
MeshInstance3D * mesh_node = Object : : cast_to < MeshInstance3D > ( p_node ) ;
if ( mesh_node & & mesh_node - > get_mesh ( ) . is_valid ( ) ) {
2022-04-12 16:07:09 +02:00
if ( ! editing_animation ) {
_fill_mesh ( scene_tree , mesh_node - > get_mesh ( ) , item ) ;
}
2021-03-19 13:57:52 +01:00
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
// Add the collider view.
MeshInstance3D * collider_view = memnew ( MeshInstance3D ) ;
collider_view - > set_name ( " collider_view " ) ;
collider_view - > set_visible ( false ) ;
2021-10-21 16:46:07 +02:00
mesh_node - > add_child ( collider_view , true ) ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
collider_view - > set_owner ( mesh_node ) ;
2020-10-17 07:08:21 +02:00
Transform3D accum_xform ;
2021-03-19 13:57:52 +01:00
Node3D * base = mesh_node ;
while ( base ) {
accum_xform = base - > get_transform ( ) * accum_xform ;
base = Object : : cast_to < Node3D > ( base - > get_parent ( ) ) ;
}
AABB aabb = accum_xform . xform ( mesh_node - > get_mesh ( ) - > get_aabb ( ) ) ;
if ( first_aabb ) {
contents_aabb = aabb ;
first_aabb = false ;
} else {
contents_aabb . merge_with ( aabb ) ;
}
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _update_scene ( ) {
2021-03-19 13:57:52 +01:00
scene_tree - > clear ( ) ;
material_tree - > clear ( ) ;
mesh_tree - > clear ( ) ;
2023-04-23 13:53:45 +02:00
// Hidden roots.
2021-03-19 13:57:52 +01:00
material_tree - > create_item ( ) ;
mesh_tree - > create_item ( ) ;
_fill_scene ( scene , nullptr ) ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _update_view_gizmos ( ) {
2022-04-12 16:07:09 +02:00
if ( ! is_visible ( ) ) {
return ;
}
2024-02-25 09:36:39 +01:00
const HashMap < StringName , Variant > & main_settings = scene_import_settings_data - > current ;
2024-03-18 04:29:29 +01:00
bool reshow_settings = false ;
2024-02-25 09:36:39 +01:00
if ( main_settings . has ( " nodes/import_as_skeleton_bones " ) ) {
bool new_import_as_skeleton = main_settings [ " nodes/import_as_skeleton_bones " ] ;
2024-03-18 04:29:29 +01:00
reshow_settings = reshow_settings | | ( new_import_as_skeleton ! = previous_import_as_skeleton ) ;
previous_import_as_skeleton = new_import_as_skeleton ;
}
if ( main_settings . has ( " animation/import_rest_as_RESET " ) ) {
bool new_rest_as_reset = main_settings [ " animation/import_rest_as_RESET " ] ;
reshow_settings = reshow_settings | | ( new_rest_as_reset ! = previous_rest_as_reset ) ;
previous_rest_as_reset = new_rest_as_reset ;
}
if ( reshow_settings ) {
_re_import ( ) ;
open_settings ( base_path ) ;
2024-02-25 09:36:39 +01:00
return ;
}
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
for ( const KeyValue < String , NodeData > & e : node_map ) {
2024-02-07 04:08:41 +01:00
// Skip import nodes that aren't MeshInstance3D.
const MeshInstance3D * mesh_node = Object : : cast_to < MeshInstance3D > ( e . value . node ) ;
if ( mesh_node = = nullptr | | mesh_node - > get_mesh ( ) . is_null ( ) ) {
continue ;
}
// Determine if the mesh collider should be visible.
2023-01-19 20:34:05 +01:00
bool show_collider_view = false ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
if ( e . value . settings . has ( SNAME ( " generate/physics " ) ) ) {
2023-01-19 20:34:05 +01:00
show_collider_view = e . value . settings [ SNAME ( " generate/physics " ) ] ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
}
2024-02-07 04:08:41 +01:00
// Get the collider_view MeshInstance3D.
2022-04-25 15:16:44 +02:00
TypedArray < Node > descendants = mesh_node - > find_children ( " collider_view " , " MeshInstance3D " ) ;
2021-12-17 19:04:35 +01:00
CRASH_COND_MSG ( descendants . is_empty ( ) , " This is unreachable, since the collider view is always created even when the collision is not used! If this is triggered there is a bug on the function `_fill_scene`. " ) ;
2024-02-07 04:08:41 +01:00
MeshInstance3D * collider_view = Object : : cast_to < MeshInstance3D > ( descendants [ 0 ] . operator Object * ( ) ) ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
2024-02-07 04:08:41 +01:00
// Regenerate the physics collider for this MeshInstance3D if either:
// - A regeneration is requested for the selected import node.
// - The collider is being made visible.
if ( ( generate_collider & & e . key = = selected_id ) | | ( show_collider_view & & ! collider_view - > is_visible ( ) ) ) {
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
// This collider_view doesn't have a mesh so we need to generate a new one.
2023-02-23 11:07:48 +01:00
Ref < ImporterMesh > mesh ;
mesh . instantiate ( ) ;
// ResourceImporterScene::get_collision_shapes() expects ImporterMesh, not Mesh.
// TODO: Duplicate code with EditorSceneFormatImporterESCN::import_scene()
// Consider making a utility function to convert from Mesh to ImporterMesh.
Ref < Mesh > mesh_3d_mesh = mesh_node - > get_mesh ( ) ;
Ref < ArrayMesh > array_mesh_3d_mesh = mesh_3d_mesh ;
if ( array_mesh_3d_mesh . is_valid ( ) ) {
// For the MeshInstance3D nodes, we need to convert the ArrayMesh to an ImporterMesh specially.
mesh - > set_name ( array_mesh_3d_mesh - > get_name ( ) ) ;
for ( int32_t blend_i = 0 ; blend_i < array_mesh_3d_mesh - > get_blend_shape_count ( ) ; blend_i + + ) {
mesh - > add_blend_shape ( array_mesh_3d_mesh - > get_blend_shape_name ( blend_i ) ) ;
}
for ( int32_t surface_i = 0 ; surface_i < array_mesh_3d_mesh - > get_surface_count ( ) ; surface_i + + ) {
mesh - > add_surface ( array_mesh_3d_mesh - > surface_get_primitive_type ( surface_i ) ,
array_mesh_3d_mesh - > surface_get_arrays ( surface_i ) ,
array_mesh_3d_mesh - > surface_get_blend_shape_arrays ( surface_i ) ,
array_mesh_3d_mesh - > surface_get_lods ( surface_i ) ,
array_mesh_3d_mesh - > surface_get_material ( surface_i ) ,
array_mesh_3d_mesh - > surface_get_name ( surface_i ) ,
array_mesh_3d_mesh - > surface_get_format ( surface_i ) ) ;
}
mesh - > set_blend_shape_mode ( array_mesh_3d_mesh - > get_blend_shape_mode ( ) ) ;
} else if ( mesh_3d_mesh . is_valid ( ) ) {
// For the MeshInstance3D nodes, we need to convert the Mesh to an ImporterMesh specially.
mesh - > set_name ( mesh_3d_mesh - > get_name ( ) ) ;
for ( int32_t surface_i = 0 ; surface_i < mesh_3d_mesh - > get_surface_count ( ) ; surface_i + + ) {
mesh - > add_surface ( mesh_3d_mesh - > surface_get_primitive_type ( surface_i ) ,
mesh_3d_mesh - > surface_get_arrays ( surface_i ) ,
Array ( ) ,
mesh_3d_mesh - > surface_get_lods ( surface_i ) ,
mesh_3d_mesh - > surface_get_material ( surface_i ) ,
mesh_3d_mesh - > surface_get_material ( surface_i ) . is_valid ( ) ? mesh_3d_mesh - > surface_get_material ( surface_i ) - > get_name ( ) : String ( ) ,
mesh_3d_mesh - > surface_get_format ( surface_i ) ) ;
}
}
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
// Generate the mesh collider.
2023-02-23 11:07:48 +01:00
Vector < Ref < Shape3D > > shapes = ResourceImporterScene : : get_collision_shapes ( mesh , e . value . settings , 1.0 ) ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
const Transform3D transform = ResourceImporterScene : : get_collision_shapes_transform ( e . value . settings ) ;
Ref < ArrayMesh > collider_view_mesh ;
collider_view_mesh . instantiate ( ) ;
for ( Ref < Shape3D > shape : shapes ) {
Ref < ArrayMesh > debug_shape_mesh ;
if ( shape . is_valid ( ) ) {
debug_shape_mesh = shape - > get_debug_mesh ( ) ;
}
if ( debug_shape_mesh . is_valid ( ) ) {
collider_view_mesh - > add_surface_from_arrays (
debug_shape_mesh - > surface_get_primitive_type ( 0 ) ,
debug_shape_mesh - > surface_get_arrays ( 0 ) ) ;
collider_view_mesh - > surface_set_material (
collider_view_mesh - > get_surface_count ( ) - 1 ,
collider_mat ) ;
}
}
collider_view - > set_mesh ( collider_view_mesh ) ;
collider_view - > set_transform ( transform ) ;
}
2024-02-07 04:08:41 +01:00
// Set the collider visibility.
collider_view - > set_visible ( show_collider_view ) ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
}
2023-01-19 20:34:05 +01:00
generate_collider = false ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _update_camera ( ) {
2021-03-19 13:57:52 +01:00
AABB camera_aabb ;
float rot_x = cam_rot_x ;
float rot_y = cam_rot_y ;
float zoom = cam_zoom ;
2021-12-09 10:42:46 +01:00
if ( selected_type = = " Node " | | selected_type . is_empty ( ) ) {
2021-03-19 13:57:52 +01:00
camera_aabb = contents_aabb ;
} else {
if ( mesh_preview - > get_mesh ( ) . is_valid ( ) ) {
camera_aabb = mesh_preview - > get_transform ( ) . xform ( mesh_preview - > get_mesh ( ) - > get_aabb ( ) ) ;
} else {
camera_aabb = AABB ( Vector3 ( - 1 , - 1 , - 1 ) , Vector3 ( 2 , 2 , 2 ) ) ;
}
if ( selected_type = = " Mesh " & & mesh_map . has ( selected_id ) ) {
const MeshData & md = mesh_map [ selected_id ] ;
rot_x = md . cam_rot_x ;
rot_y = md . cam_rot_y ;
zoom = md . cam_zoom ;
} else if ( selected_type = = " Material " & & material_map . has ( selected_id ) ) {
const MaterialData & md = material_map [ selected_id ] ;
rot_x = md . cam_rot_x ;
rot_y = md . cam_rot_y ;
zoom = md . cam_zoom ;
}
}
2021-09-20 20:48:52 +02:00
Vector3 center = camera_aabb . get_center ( ) ;
2021-03-19 13:57:52 +01:00
float camera_size = camera_aabb . get_longest_axis_size ( ) ;
camera - > set_orthogonal ( camera_size * zoom , 0.0001 , camera_size * 2 ) ;
2020-10-17 07:08:21 +02:00
Transform3D xf ;
2023-09-30 05:02:22 +02:00
xf . basis = Basis ( Vector3 ( 0 , 1 , 0 ) , rot_y ) * Basis ( Vector3 ( 1 , 0 , 0 ) , rot_x ) ;
2021-03-19 13:57:52 +01:00
xf . origin = center ;
2022-07-16 11:47:54 +02:00
xf . translate_local ( 0 , 0 , camera_size ) ;
2021-03-19 13:57:52 +01:00
camera - > set_transform ( xf ) ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _load_default_subresource_settings ( HashMap < StringName , Variant > & settings , const String & p_type , const String & p_import_id , ResourceImporterScene : : InternalImportCategory p_category ) {
2021-03-19 13:57:52 +01:00
if ( base_subresource_settings . has ( p_type ) ) {
Dictionary d = base_subresource_settings [ p_type ] ;
if ( d . has ( p_import_id ) ) {
d = d [ p_import_id ] ;
List < ResourceImporterScene : : ImportOption > options ;
2022-04-12 16:07:09 +02:00
if ( editing_animation ) {
ResourceImporterScene : : get_animation_singleton ( ) - > get_internal_import_options ( p_category , & options ) ;
} else {
ResourceImporterScene : : get_scene_singleton ( ) - > get_internal_import_options ( p_category , & options ) ;
}
2021-07-24 15:46:25 +02:00
for ( const ResourceImporterScene : : ImportOption & E : options ) {
2021-07-16 05:45:57 +02:00
String key = E . option . name ;
2021-03-19 13:57:52 +01:00
if ( d . has ( key ) ) {
settings [ key ] = d [ key ] ;
}
}
}
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : request_generate_collider ( ) {
2023-01-19 20:34:05 +01:00
generate_collider = true ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : update_view ( ) {
2022-04-12 16:07:09 +02:00
update_view_timer - > start ( ) ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : open_settings ( const String & p_path , bool p_for_animation ) {
2021-03-19 13:57:52 +01:00
if ( scene ) {
2024-02-25 09:36:39 +01:00
_cleanup ( ) ;
2021-03-19 13:57:52 +01:00
memdelete ( scene ) ;
scene = nullptr ;
}
2022-04-12 16:07:09 +02:00
editing_animation = p_for_animation ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
scene_import_settings_data - > settings = nullptr ;
2022-04-12 16:07:09 +02:00
scene_import_settings_data - > path = p_path ;
2023-04-23 13:53:45 +02:00
// Visibility.
2022-04-12 16:07:09 +02:00
data_mode - > set_tab_hidden ( 1 , p_for_animation ) ;
data_mode - > set_tab_hidden ( 2 , p_for_animation ) ;
2023-02-24 03:38:50 +01:00
if ( p_for_animation ) {
data_mode - > set_current_tab ( 0 ) ;
}
2022-04-12 16:07:09 +02:00
action_menu - > get_popup ( ) - > set_item_disabled ( action_menu - > get_popup ( ) - > get_item_id ( ACTION_EXTRACT_MATERIALS ) , p_for_animation ) ;
action_menu - > get_popup ( ) - > set_item_disabled ( action_menu - > get_popup ( ) - > get_item_id ( ACTION_CHOOSE_MESH_SAVE_PATHS ) , p_for_animation ) ;
2021-03-19 13:57:52 +01:00
base_path = p_path ;
mesh_set . clear ( ) ;
2022-12-15 04:54:48 +01:00
animation_map . clear ( ) ;
2021-03-19 13:57:52 +01:00
material_map . clear ( ) ;
2022-12-09 17:01:40 +01:00
unnamed_material_name_map . clear ( ) ;
2021-03-19 13:57:52 +01:00
mesh_map . clear ( ) ;
node_map . clear ( ) ;
defaults . clear ( ) ;
2022-05-01 02:03:12 +02:00
mesh_preview - > hide ( ) ;
2021-03-19 13:57:52 +01:00
selected_id = " " ;
selected_type = " " ;
cam_rot_x = - Math_PI / 4 ;
cam_rot_y = - Math_PI / 4 ;
cam_zoom = 1 ;
{
base_subresource_settings . clear ( ) ;
Ref < ConfigFile > config ;
2021-06-18 00:03:09 +02:00
config . instantiate ( ) ;
2021-03-19 13:57:52 +01:00
Error err = config - > load ( p_path + " .import " ) ;
if ( err = = OK ) {
List < String > keys ;
config - > get_section_keys ( " params " , & keys ) ;
2021-07-24 15:46:25 +02:00
for ( const String & E : keys ) {
2021-07-16 05:45:57 +02:00
Variant value = config - > get_value ( " params " , E ) ;
if ( E = = " _subresources " ) {
2021-03-19 13:57:52 +01:00
base_subresource_settings = value ;
} else {
2021-07-16 05:45:57 +02:00
defaults [ E ] = value ;
2021-03-19 13:57:52 +01:00
}
}
}
}
2022-07-01 14:03:40 +02:00
scene = ResourceImporterScene : : get_scene_singleton ( ) - > pre_import ( p_path , defaults ) ; // Use the scene singleton here because we want to see the full thing.
if ( scene = = nullptr ) {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Error opening scene " ) ) ;
return ;
}
2021-03-19 13:57:52 +01:00
first_aabb = true ;
_update_scene ( ) ;
base_viewport - > add_child ( scene ) ;
2022-03-20 06:41:22 +01:00
inspector - > edit ( nullptr ) ;
2021-03-19 13:57:52 +01:00
if ( first_aabb ) {
contents_aabb = AABB ( Vector3 ( - 1 , - 1 , - 1 ) , Vector3 ( 2 , 2 , 2 ) ) ;
first_aabb = false ;
}
2024-02-25 09:36:39 +01:00
const HashMap < StringName , Variant > & main_settings = scene_import_settings_data - > current ;
if ( main_settings . has ( " nodes/import_as_skeleton_bones " ) ) {
previous_import_as_skeleton = main_settings [ " nodes/import_as_skeleton_bones " ] ;
}
2024-03-18 04:29:29 +01:00
if ( main_settings . has ( " animation/import_rest_as_RESET " ) ) {
previous_rest_as_reset = main_settings [ " animation/import_rest_as_RESET " ] ;
}
2021-03-19 13:57:52 +01:00
popup_centered_ratio ( ) ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
_update_view_gizmos ( ) ;
2021-03-19 13:57:52 +01:00
_update_camera ( ) ;
2022-04-03 14:01:38 +02:00
// Start with the root item (Scene) selected.
scene_tree - > get_root ( ) - > select ( 0 ) ;
2022-04-12 16:07:09 +02:00
if ( p_for_animation ) {
set_title ( vformat ( TTR ( " Advanced Import Settings for AnimationLibrary '%s' " ) , base_path . get_file ( ) ) ) ;
} else {
set_title ( vformat ( TTR ( " Advanced Import Settings for Scene '%s' " ) , base_path . get_file ( ) ) ) ;
}
2021-03-19 13:57:52 +01:00
}
2023-10-06 09:00:36 +02:00
SceneImportSettingsDialog * SceneImportSettingsDialog : : singleton = nullptr ;
2021-03-19 13:57:52 +01:00
2023-10-06 09:00:36 +02:00
SceneImportSettingsDialog * SceneImportSettingsDialog : : get_singleton ( ) {
2021-03-19 13:57:52 +01:00
return singleton ;
}
2023-10-06 09:00:36 +02:00
Node * SceneImportSettingsDialog : : get_selected_node ( ) {
2022-06-27 10:06:50 +02:00
if ( selected_id = = " " ) {
return nullptr ;
}
return node_map [ selected_id ] . node ;
}
2024-02-15 17:25:58 +01:00
void SceneImportSettingsDialog : : _select ( Tree * p_from , const String & p_type , const String & p_id ) {
2021-03-19 13:57:52 +01:00
selecting = true ;
2022-04-12 16:07:09 +02:00
scene_import_settings_data - > hide_options = false ;
2021-03-19 13:57:52 +01:00
if ( p_type = = " Node " ) {
2023-04-23 13:53:45 +02:00
node_selected - > hide ( ) ; // Always hide just in case.
2021-03-19 13:57:52 +01:00
mesh_preview - > hide ( ) ;
2023-04-23 13:53:45 +02:00
_reset_animation ( ) ;
2021-03-19 13:57:52 +01:00
if ( Object : : cast_to < Node3D > ( scene ) ) {
Object : : cast_to < Node3D > ( scene ) - > show ( ) ;
}
material_tree - > deselect_all ( ) ;
mesh_tree - > deselect_all ( ) ;
NodeData & nd = node_map [ p_id ] ;
MeshInstance3D * mi = Object : : cast_to < MeshInstance3D > ( nd . node ) ;
if ( mi ) {
Ref < Mesh > base_mesh = mi - > get_mesh ( ) ;
if ( base_mesh . is_valid ( ) ) {
AABB aabb = base_mesh - > get_aabb ( ) ;
2020-10-17 07:08:21 +02:00
Transform3D aabb_xf ;
2021-03-19 13:57:52 +01:00
aabb_xf . basis . scale ( aabb . size ) ;
aabb_xf . origin = aabb . position ;
aabb_xf = mi - > get_global_transform ( ) * aabb_xf ;
node_selected - > set_transform ( aabb_xf ) ;
node_selected - > show ( ) ;
}
}
if ( nd . node = = scene ) {
scene_import_settings_data - > settings = & defaults ;
scene_import_settings_data - > category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MAX ;
} else {
scene_import_settings_data - > settings = & nd . settings ;
if ( mi ) {
scene_import_settings_data - > category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE ;
2022-04-12 16:07:09 +02:00
scene_import_settings_data - > hide_options = editing_animation ;
2021-03-19 13:57:52 +01:00
} else if ( Object : : cast_to < AnimationPlayer > ( nd . node ) ) {
scene_import_settings_data - > category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE ;
2022-06-27 10:06:50 +02:00
} else if ( Object : : cast_to < Skeleton3D > ( nd . node ) ) {
scene_import_settings_data - > category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE ;
2021-03-19 13:57:52 +01:00
} else {
scene_import_settings_data - > category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_NODE ;
2022-04-12 16:07:09 +02:00
scene_import_settings_data - > hide_options = editing_animation ;
2021-03-19 13:57:52 +01:00
}
}
} else if ( p_type = = " Animation " ) {
2023-04-23 13:53:45 +02:00
node_selected - > hide ( ) ; // Always hide just in case.
2021-03-19 13:57:52 +01:00
mesh_preview - > hide ( ) ;
2023-04-23 13:53:45 +02:00
_reset_animation ( p_id ) ;
2021-03-19 13:57:52 +01:00
if ( Object : : cast_to < Node3D > ( scene ) ) {
Object : : cast_to < Node3D > ( scene ) - > show ( ) ;
}
material_tree - > deselect_all ( ) ;
mesh_tree - > deselect_all ( ) ;
AnimationData & ad = animation_map [ p_id ] ;
scene_import_settings_data - > settings = & ad . settings ;
scene_import_settings_data - > category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_ANIMATION ;
} else if ( p_type = = " Mesh " ) {
node_selected - > hide ( ) ;
if ( Object : : cast_to < Node3D > ( scene ) ) {
Object : : cast_to < Node3D > ( scene ) - > hide ( ) ;
}
MeshData & md = mesh_map [ p_id ] ;
2022-12-27 15:03:18 +01:00
if ( md . mesh_node ! = nullptr ) {
if ( p_from ! = mesh_tree ) {
md . mesh_node - > uncollapse_tree ( ) ;
md . mesh_node - > select ( 0 ) ;
mesh_tree - > ensure_cursor_is_visible ( ) ;
}
if ( p_from ! = scene_tree ) {
md . scene_node - > uncollapse_tree ( ) ;
md . scene_node - > select ( 0 ) ;
scene_tree - > ensure_cursor_is_visible ( ) ;
}
2021-03-19 13:57:52 +01:00
}
mesh_preview - > set_mesh ( md . mesh ) ;
mesh_preview - > show ( ) ;
2023-04-23 13:53:45 +02:00
_reset_animation ( ) ;
2021-03-19 13:57:52 +01:00
material_tree - > deselect_all ( ) ;
scene_import_settings_data - > settings = & md . settings ;
scene_import_settings_data - > category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MESH ;
} else if ( p_type = = " Material " ) {
node_selected - > hide ( ) ;
if ( Object : : cast_to < Node3D > ( scene ) ) {
Object : : cast_to < Node3D > ( scene ) - > hide ( ) ;
}
mesh_preview - > show ( ) ;
2023-04-23 13:53:45 +02:00
_reset_animation ( ) ;
2021-03-19 13:57:52 +01:00
MaterialData & md = material_map [ p_id ] ;
material_preview - > set_material ( md . material ) ;
mesh_preview - > set_mesh ( material_preview ) ;
if ( p_from ! = mesh_tree ) {
md . mesh_node - > uncollapse_tree ( ) ;
md . mesh_node - > select ( 0 ) ;
mesh_tree - > ensure_cursor_is_visible ( ) ;
}
if ( p_from ! = scene_tree ) {
md . scene_node - > uncollapse_tree ( ) ;
md . scene_node - > select ( 0 ) ;
scene_tree - > ensure_cursor_is_visible ( ) ;
}
if ( p_from ! = material_tree ) {
md . material_node - > uncollapse_tree ( ) ;
md . material_node - > select ( 0 ) ;
material_tree - > ensure_cursor_is_visible ( ) ;
}
scene_import_settings_data - > settings = & md . settings ;
scene_import_settings_data - > category = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MATERIAL ;
}
selected_type = p_type ;
selected_id = p_id ;
selecting = false ;
_update_camera ( ) ;
List < ResourceImporter : : ImportOption > options ;
2022-04-12 16:07:09 +02:00
if ( editing_animation ) {
if ( scene_import_settings_data - > category = = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MAX ) {
ResourceImporterScene : : get_animation_singleton ( ) - > get_import_options ( base_path , & options ) ;
} else {
ResourceImporterScene : : get_animation_singleton ( ) - > get_internal_import_options ( scene_import_settings_data - > category , & options ) ;
}
2021-03-19 13:57:52 +01:00
} else {
2022-04-12 16:07:09 +02:00
if ( scene_import_settings_data - > category = = ResourceImporterScene : : INTERNAL_IMPORT_CATEGORY_MAX ) {
ResourceImporterScene : : get_scene_singleton ( ) - > get_import_options ( base_path , & options ) ;
} else {
ResourceImporterScene : : get_scene_singleton ( ) - > get_internal_import_options ( scene_import_settings_data - > category , & options ) ;
}
2021-03-19 13:57:52 +01:00
}
scene_import_settings_data - > defaults . clear ( ) ;
scene_import_settings_data - > current . clear ( ) ;
2022-04-12 16:07:09 +02:00
if ( scene_import_settings_data - > settings ) {
for ( const ResourceImporter : : ImportOption & E : options ) {
scene_import_settings_data - > defaults [ E . option . name ] = E . default_value ;
2023-04-23 13:53:45 +02:00
// Needed for visibility toggling (fails if something is missing).
2022-04-12 16:07:09 +02:00
if ( scene_import_settings_data - > settings - > has ( E . option . name ) ) {
scene_import_settings_data - > current [ E . option . name ] = ( * scene_import_settings_data - > settings ) [ E . option . name ] ;
} else {
scene_import_settings_data - > current [ E . option . name ] = E . default_value ;
}
2021-03-19 13:57:52 +01:00
}
}
2022-04-12 16:07:09 +02:00
2021-03-19 13:57:52 +01:00
scene_import_settings_data - > options = options ;
inspector - > edit ( scene_import_settings_data ) ;
scene_import_settings_data - > notify_property_list_changed ( ) ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _inspector_property_edited ( const String & p_name ) {
2023-04-23 13:53:45 +02:00
if ( p_name = = " settings/loop_mode " ) {
if ( ! animation_map . has ( selected_id ) ) {
return ;
}
HashMap < StringName , Variant > settings = animation_map [ selected_id ] . settings ;
if ( settings . has ( p_name ) ) {
animation_loop_mode = static_cast < Animation : : LoopMode > ( ( int ) settings [ p_name ] ) ;
} else {
animation_loop_mode = Animation : : LoopMode : : LOOP_NONE ;
}
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _reset_bone_transforms ( ) {
2023-04-23 13:53:45 +02:00
for ( Skeleton3D * skeleton : skeletons ) {
skeleton - > reset_bone_poses ( ) ;
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _play_animation ( ) {
2023-04-23 13:53:45 +02:00
if ( animation_player = = nullptr ) {
return ;
}
StringName id = StringName ( selected_id ) ;
if ( animation_player - > has_animation ( id ) ) {
if ( animation_player - > is_playing ( ) ) {
animation_player - > pause ( ) ;
2023-08-13 02:33:39 +02:00
animation_play_button - > set_icon ( get_editor_theme_icon ( SNAME ( " MainPlay " ) ) ) ;
2023-04-23 13:53:45 +02:00
set_process ( false ) ;
} else {
animation_player - > play ( id ) ;
2023-08-13 02:33:39 +02:00
animation_play_button - > set_icon ( get_editor_theme_icon ( SNAME ( " Pause " ) ) ) ;
2023-04-23 13:53:45 +02:00
set_process ( true ) ;
}
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _stop_current_animation ( ) {
2023-04-23 13:53:45 +02:00
animation_pingpong = false ;
animation_player - > stop ( ) ;
2023-08-13 02:33:39 +02:00
animation_play_button - > set_icon ( get_editor_theme_icon ( SNAME ( " MainPlay " ) ) ) ;
2023-04-23 13:53:45 +02:00
animation_slider - > set_value_no_signal ( 0.0 ) ;
set_process ( false ) ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _reset_animation ( const String & p_animation_name ) {
2023-04-23 13:53:45 +02:00
if ( p_animation_name . is_empty ( ) ) {
animation_preview - > hide ( ) ;
if ( animation_player ! = nullptr & & animation_player - > is_playing ( ) ) {
animation_player - > stop ( ) ;
}
2023-08-13 02:33:39 +02:00
animation_play_button - > set_icon ( get_editor_theme_icon ( SNAME ( " MainPlay " ) ) ) ;
2023-04-23 13:53:45 +02:00
_reset_bone_transforms ( ) ;
set_process ( false ) ;
} else {
_reset_bone_transforms ( ) ;
animation_preview - > show ( ) ;
animation_loop_mode = Animation : : LoopMode : : LOOP_NONE ;
animation_pingpong = false ;
if ( animation_map . has ( p_animation_name ) ) {
HashMap < StringName , Variant > settings = animation_map [ p_animation_name ] . settings ;
if ( settings . has ( " settings/loop_mode " ) ) {
animation_loop_mode = static_cast < Animation : : LoopMode > ( ( int ) settings [ " settings/loop_mode " ] ) ;
}
}
if ( animation_player - > is_playing ( ) & & animation_loop_mode ! = Animation : : LoopMode : : LOOP_NONE ) {
animation_player - > play ( p_animation_name ) ;
} else {
animation_player - > stop ( true ) ;
2023-08-13 02:33:39 +02:00
animation_play_button - > set_icon ( get_editor_theme_icon ( SNAME ( " MainPlay " ) ) ) ;
2023-04-23 13:53:45 +02:00
animation_player - > set_assigned_animation ( p_animation_name ) ;
animation_player - > seek ( 0.0 , true ) ;
animation_slider - > set_value_no_signal ( 0.0 ) ;
set_process ( false ) ;
}
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _animation_slider_value_changed ( double p_value ) {
2023-04-23 13:53:45 +02:00
if ( animation_player = = nullptr | | ! animation_map . has ( selected_id ) | | animation_map [ selected_id ] . animation . is_null ( ) ) {
return ;
}
if ( animation_player - > is_playing ( ) ) {
animation_player - > stop ( ) ;
2023-08-13 02:33:39 +02:00
animation_play_button - > set_icon ( get_editor_theme_icon ( SNAME ( " MainPlay " ) ) ) ;
2023-04-23 13:53:45 +02:00
set_process ( false ) ;
}
animation_player - > seek ( p_value * animation_map [ selected_id ] . animation - > get_length ( ) , true ) ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _animation_finished ( const StringName & p_name ) {
2023-04-23 13:53:45 +02:00
Animation : : LoopMode loop_mode = animation_loop_mode ;
switch ( loop_mode ) {
case Animation : : LOOP_NONE : {
2023-08-13 02:33:39 +02:00
animation_play_button - > set_icon ( get_editor_theme_icon ( SNAME ( " MainPlay " ) ) ) ;
2023-04-23 13:53:45 +02:00
animation_slider - > set_value_no_signal ( 1.0 ) ;
set_process ( false ) ;
} break ;
case Animation : : LOOP_LINEAR : {
animation_player - > play ( p_name ) ;
} break ;
case Animation : : LOOP_PINGPONG : {
if ( animation_pingpong ) {
animation_player - > play ( p_name ) ;
} else {
animation_player - > play_backwards ( p_name ) ;
}
animation_pingpong = ! animation_pingpong ;
} break ;
default : {
} break ;
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _material_tree_selected ( ) {
2021-03-19 13:57:52 +01:00
if ( selecting ) {
return ;
}
TreeItem * item = material_tree - > get_selected ( ) ;
String type = item - > get_meta ( " type " ) ;
String import_id = item - > get_meta ( " import_id " ) ;
_select ( material_tree , type , import_id ) ;
}
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _mesh_tree_selected ( ) {
2021-03-19 13:57:52 +01:00
if ( selecting ) {
return ;
}
TreeItem * item = mesh_tree - > get_selected ( ) ;
String type = item - > get_meta ( " type " ) ;
String import_id = item - > get_meta ( " import_id " ) ;
_select ( mesh_tree , type , import_id ) ;
}
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _scene_tree_selected ( ) {
2021-03-19 13:57:52 +01:00
if ( selecting ) {
return ;
}
TreeItem * item = scene_tree - > get_selected ( ) ;
String type = item - > get_meta ( " type " ) ;
String import_id = item - > get_meta ( " import_id " ) ;
_select ( scene_tree , type , import_id ) ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _cleanup ( ) {
2023-04-23 13:53:45 +02:00
skeletons . clear ( ) ;
if ( animation_player ! = nullptr ) {
2023-10-06 09:00:36 +02:00
animation_player - > disconnect ( SNAME ( " animation_finished " ) , callable_mp ( this , & SceneImportSettingsDialog : : _animation_finished ) ) ;
2023-04-23 13:53:45 +02:00
animation_player = nullptr ;
}
set_process ( false ) ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _viewport_input ( const Ref < InputEvent > & p_input ) {
2021-03-19 13:57:52 +01:00
float * rot_x = & cam_rot_x ;
float * rot_y = & cam_rot_y ;
float * zoom = & cam_zoom ;
if ( selected_type = = " Mesh " & & mesh_map . has ( selected_id ) ) {
MeshData & md = mesh_map [ selected_id ] ;
rot_x = & md . cam_rot_x ;
rot_y = & md . cam_rot_y ;
zoom = & md . cam_zoom ;
} else if ( selected_type = = " Material " & & material_map . has ( selected_id ) ) {
MaterialData & md = material_map [ selected_id ] ;
rot_x = & md . cam_rot_x ;
rot_y = & md . cam_rot_y ;
zoom = & md . cam_zoom ;
}
Ref < InputEventMouseMotion > mm = p_input ;
2023-01-08 00:55:54 +01:00
if ( mm . is_valid ( ) & & ( mm - > get_button_mask ( ) . has_flag ( MouseButtonMask : : LEFT ) ) ) {
2021-03-19 13:57:52 +01:00
( * rot_x ) - = mm - > get_relative ( ) . y * 0.01 * EDSCALE ;
( * rot_y ) - = mm - > get_relative ( ) . x * 0.01 * EDSCALE ;
( * rot_x ) = CLAMP ( ( * rot_x ) , - Math_PI / 2 , Math_PI / 2 ) ;
_update_camera ( ) ;
}
2023-11-09 12:50:13 +01:00
if ( mm . is_valid ( ) & & DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_CURSOR_SHAPE ) ) {
DisplayServer : : get_singleton ( ) - > cursor_set_shape ( DisplayServer : : CursorShape : : CURSOR_ARROW ) ;
}
2021-03-19 13:57:52 +01:00
Ref < InputEventMouseButton > mb = p_input ;
2021-08-13 23:31:57 +02:00
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = MouseButton : : WHEEL_DOWN ) {
2021-03-19 13:57:52 +01:00
( * zoom ) * = 1.1 ;
if ( ( * zoom ) > 10.0 ) {
( * zoom ) = 10.0 ;
}
_update_camera ( ) ;
}
2021-08-13 23:31:57 +02:00
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = MouseButton : : WHEEL_UP ) {
2021-03-19 13:57:52 +01:00
( * zoom ) / = 1.1 ;
if ( ( * zoom ) < 0.1 ) {
( * zoom ) = 0.1 ;
}
_update_camera ( ) ;
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _re_import ( ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , Variant > main_settings ;
2021-03-19 13:57:52 +01:00
2023-07-26 00:06:15 +02:00
main_settings = scene_import_settings_data - > current ;
2021-03-19 13:57:52 +01:00
main_settings . erase ( " _subresources " ) ;
Dictionary nodes ;
Dictionary materials ;
Dictionary meshes ;
Dictionary animations ;
Dictionary subresources ;
2021-08-09 22:13:42 +02:00
for ( KeyValue < String , NodeData > & E : node_map ) {
if ( E . value . settings . size ( ) ) {
2021-03-19 13:57:52 +01:00
Dictionary d ;
2021-08-09 22:13:42 +02:00
for ( const KeyValue < StringName , Variant > & F : E . value . settings ) {
d [ String ( F . key ) ] = F . value ;
2021-03-19 13:57:52 +01:00
}
2021-08-09 22:13:42 +02:00
nodes [ E . key ] = d ;
2021-03-19 13:57:52 +01:00
}
}
if ( nodes . size ( ) ) {
subresources [ " nodes " ] = nodes ;
}
2021-08-09 22:13:42 +02:00
for ( KeyValue < String , MaterialData > & E : material_map ) {
if ( E . value . settings . size ( ) ) {
2021-03-19 13:57:52 +01:00
Dictionary d ;
2021-08-09 22:13:42 +02:00
for ( const KeyValue < StringName , Variant > & F : E . value . settings ) {
d [ String ( F . key ) ] = F . value ;
2021-03-19 13:57:52 +01:00
}
2021-08-09 22:13:42 +02:00
materials [ E . key ] = d ;
2021-03-19 13:57:52 +01:00
}
}
if ( materials . size ( ) ) {
subresources [ " materials " ] = materials ;
}
2021-08-09 22:13:42 +02:00
for ( KeyValue < String , MeshData > & E : mesh_map ) {
if ( E . value . settings . size ( ) ) {
2021-03-19 13:57:52 +01:00
Dictionary d ;
2021-08-09 22:13:42 +02:00
for ( const KeyValue < StringName , Variant > & F : E . value . settings ) {
d [ String ( F . key ) ] = F . value ;
2021-03-19 13:57:52 +01:00
}
2021-08-09 22:13:42 +02:00
meshes [ E . key ] = d ;
2021-03-19 13:57:52 +01:00
}
}
if ( meshes . size ( ) ) {
subresources [ " meshes " ] = meshes ;
}
2021-08-09 22:13:42 +02:00
for ( KeyValue < String , AnimationData > & E : animation_map ) {
if ( E . value . settings . size ( ) ) {
2021-03-19 13:57:52 +01:00
Dictionary d ;
2021-08-09 22:13:42 +02:00
for ( const KeyValue < StringName , Variant > & F : E . value . settings ) {
d [ String ( F . key ) ] = F . value ;
2021-03-19 13:57:52 +01:00
}
2021-08-09 22:13:42 +02:00
animations [ E . key ] = d ;
2021-03-19 13:57:52 +01:00
}
}
if ( animations . size ( ) ) {
subresources [ " animations " ] = animations ;
}
if ( subresources . size ( ) ) {
main_settings [ " _subresources " ] = subresources ;
}
2024-02-25 09:36:39 +01:00
_cleanup ( ) ; // Prevent skeletons and other pointers from pointing to dangling references.
2022-04-12 16:07:09 +02:00
EditorFileSystem : : get_singleton ( ) - > reimport_file_with_custom_parameters ( base_path , editing_animation ? " animation_library " : " scene " , main_settings ) ;
2021-03-19 13:57:52 +01:00
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _notification ( int p_what ) {
2022-02-16 03:44:22 +01:00
switch ( p_what ) {
case NOTIFICATION_READY : {
2023-10-06 09:00:36 +02:00
connect ( " confirmed " , callable_mp ( this , & SceneImportSettingsDialog : : _re_import ) ) ;
2022-02-16 03:44:22 +01:00
} break ;
2022-03-23 02:46:59 +01:00
2023-04-03 18:01:11 +02:00
case NOTIFICATION_THEME_CHANGED : {
2023-10-19 18:05:19 +02:00
action_menu - > begin_bulk_theme_override ( ) ;
2023-04-03 18:01:11 +02:00
action_menu - > add_theme_style_override ( " normal " , get_theme_stylebox ( " normal " , " Button " ) ) ;
action_menu - > add_theme_style_override ( " hover " , get_theme_stylebox ( " hover " , " Button " ) ) ;
action_menu - > add_theme_style_override ( " pressed " , get_theme_stylebox ( " pressed " , " Button " ) ) ;
2023-10-19 18:05:19 +02:00
action_menu - > end_bulk_theme_override ( ) ;
2023-04-23 13:53:45 +02:00
if ( animation_player ! = nullptr & & animation_player - > is_playing ( ) ) {
2023-08-13 02:33:39 +02:00
animation_play_button - > set_icon ( get_editor_theme_icon ( SNAME ( " Pause " ) ) ) ;
2023-04-23 13:53:45 +02:00
} else {
2023-08-13 02:33:39 +02:00
animation_play_button - > set_icon ( get_editor_theme_icon ( SNAME ( " MainPlay " ) ) ) ;
2023-04-23 13:53:45 +02:00
}
2023-08-13 02:33:39 +02:00
animation_stop_button - > set_icon ( get_editor_theme_icon ( SNAME ( " Stop " ) ) ) ;
2023-04-23 13:53:45 +02:00
} break ;
case NOTIFICATION_PROCESS : {
if ( animation_player ! = nullptr ) {
animation_slider - > set_value_no_signal ( animation_player - > get_current_animation_position ( ) / animation_player - > get_current_animation_length ( ) ) ;
}
} break ;
case NOTIFICATION_VISIBILITY_CHANGED : {
if ( ! is_visible ( ) ) {
_cleanup ( ) ;
}
2023-04-03 18:01:11 +02:00
} break ;
2021-03-19 13:57:52 +01:00
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _menu_callback ( int p_id ) {
2021-03-19 13:57:52 +01:00
switch ( p_id ) {
case ACTION_EXTRACT_MATERIALS : {
2022-12-20 18:57:10 +01:00
save_path - > set_title ( TTR ( " Select folder to extract material resources " ) ) ;
2021-03-19 13:57:52 +01:00
external_extension_type - > select ( 0 ) ;
} break ;
case ACTION_CHOOSE_MESH_SAVE_PATHS : {
2022-12-20 18:57:10 +01:00
save_path - > set_title ( TTR ( " Select folder where mesh resources will save on import " ) ) ;
2021-03-19 13:57:52 +01:00
external_extension_type - > select ( 1 ) ;
} break ;
case ACTION_CHOOSE_ANIMATION_SAVE_PATHS : {
2022-12-20 18:57:10 +01:00
save_path - > set_title ( TTR ( " Select folder where animations will save on import " ) ) ;
2021-03-19 13:57:52 +01:00
external_extension_type - > select ( 1 ) ;
} break ;
}
save_path - > set_current_dir ( base_path . get_base_dir ( ) ) ;
current_action = p_id ;
save_path - > popup_centered_ratio ( ) ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _save_path_changed ( const String & p_path ) {
2021-03-19 13:57:52 +01:00
save_path_item - > set_text ( 1 , p_path ) ;
if ( FileAccess : : exists ( p_path ) ) {
2023-03-27 12:06:07 +02:00
save_path_item - > set_text ( 2 , TTR ( " Warning: File exists " ) ) ;
2022-08-29 15:55:49 +02:00
save_path_item - > set_tooltip_text ( 2 , TTR ( " Existing file with the same name will be replaced. " ) ) ;
2023-08-13 02:33:39 +02:00
save_path_item - > set_icon ( 2 , get_editor_theme_icon ( SNAME ( " StatusWarning " ) ) ) ;
2021-03-19 13:57:52 +01:00
} else {
2023-03-27 12:06:07 +02:00
save_path_item - > set_text ( 2 , TTR ( " Will create new file " ) ) ;
2023-08-13 02:33:39 +02:00
save_path_item - > set_icon ( 2 , get_editor_theme_icon ( SNAME ( " StatusSuccess " ) ) ) ;
2021-03-19 13:57:52 +01:00
}
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _browse_save_callback ( Object * p_item , int p_column , int p_id , MouseButton p_button ) {
2021-09-18 09:33:18 +02:00
if ( p_button ! = MouseButton : : LEFT ) {
return ;
}
2021-03-19 13:57:52 +01:00
TreeItem * item = Object : : cast_to < TreeItem > ( p_item ) ;
String path = item - > get_text ( 1 ) ;
item_save_path - > set_current_file ( path ) ;
save_path_item = item ;
item_save_path - > popup_centered_ratio ( ) ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _save_dir_callback ( const String & p_path ) {
2021-03-19 13:57:52 +01:00
external_path_tree - > clear ( ) ;
TreeItem * root = external_path_tree - > create_item ( ) ;
save_path_items . clear ( ) ;
switch ( current_action ) {
case ACTION_EXTRACT_MATERIALS : {
2021-08-09 22:13:42 +02:00
for ( const KeyValue < String , MaterialData > & E : material_map ) {
MaterialData & md = material_map [ E . key ] ;
2021-03-19 13:57:52 +01:00
TreeItem * item = external_path_tree - > create_item ( root ) ;
String name = md . material_node - > get_text ( 0 ) ;
item - > set_cell_mode ( 0 , TreeItem : : CELL_MODE_CHECK ) ;
2023-08-13 02:33:39 +02:00
item - > set_icon ( 0 , get_editor_theme_icon ( SNAME ( " StandardMaterial3D " ) ) ) ;
2021-03-19 13:57:52 +01:00
item - > set_text ( 0 , name ) ;
if ( md . has_import_id ) {
if ( md . settings . has ( " use_external/enabled " ) & & bool ( md . settings [ " use_external/enabled " ] ) ) {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " Already External " ) ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 2 , TTR ( " This material already references an external file, no action will be taken. \n Disable the external property for it to be extracted again. " ) ) ;
2021-03-19 13:57:52 +01:00
} else {
2021-08-09 22:13:42 +02:00
item - > set_metadata ( 0 , E . key ) ;
2021-03-19 13:57:52 +01:00
item - > set_editable ( 0 , true ) ;
item - > set_checked ( 0 , true ) ;
2022-08-30 02:34:01 +02:00
String path = p_path . path_join ( name ) ;
2021-03-19 13:57:52 +01:00
if ( external_extension_type - > get_selected ( ) = = 0 ) {
path + = " .tres " ;
} else {
path + = " .res " ;
}
item - > set_text ( 1 , path ) ;
if ( FileAccess : : exists ( path ) ) {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " Warning: File exists " ) ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 2 , TTR ( " Existing file with the same name will be replaced. " ) ) ;
2023-08-13 02:33:39 +02:00
item - > set_icon ( 2 , get_editor_theme_icon ( SNAME ( " StatusWarning " ) ) ) ;
2021-03-19 13:57:52 +01:00
} else {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " Will create new file " ) ) ;
2023-08-13 02:33:39 +02:00
item - > set_icon ( 2 , get_editor_theme_icon ( SNAME ( " StatusSuccess " ) ) ) ;
2021-03-19 13:57:52 +01:00
}
2023-08-13 02:33:39 +02:00
item - > add_button ( 1 , get_editor_theme_icon ( SNAME ( " Folder " ) ) ) ;
2021-03-19 13:57:52 +01:00
}
} else {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " No import ID " ) ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 2 , TTR ( " Material has no name nor any other way to identify on re-import. \n Please name it or ensure it is exported with an unique ID. " ) ) ;
2023-08-13 02:33:39 +02:00
item - > set_icon ( 2 , get_editor_theme_icon ( SNAME ( " StatusError " ) ) ) ;
2021-03-19 13:57:52 +01:00
}
save_path_items . push_back ( item ) ;
}
external_paths - > set_title ( TTR ( " Extract Materials to Resource Files " ) ) ;
2022-07-08 02:31:19 +02:00
external_paths - > set_ok_button_text ( TTR ( " Extract " ) ) ;
2021-03-19 13:57:52 +01:00
} break ;
case ACTION_CHOOSE_MESH_SAVE_PATHS : {
2021-08-09 22:13:42 +02:00
for ( const KeyValue < String , MeshData > & E : mesh_map ) {
MeshData & md = mesh_map [ E . key ] ;
2021-03-19 13:57:52 +01:00
TreeItem * item = external_path_tree - > create_item ( root ) ;
String name = md . mesh_node - > get_text ( 0 ) ;
item - > set_cell_mode ( 0 , TreeItem : : CELL_MODE_CHECK ) ;
2023-09-25 14:52:58 +02:00
item - > set_icon ( 0 , get_editor_theme_icon ( SNAME ( " MeshItem " ) ) ) ;
2021-03-19 13:57:52 +01:00
item - > set_text ( 0 , name ) ;
if ( md . has_import_id ) {
if ( md . settings . has ( " save_to_file/enabled " ) & & bool ( md . settings [ " save_to_file/enabled " ] ) ) {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " Already Saving " ) ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 2 , TTR ( " This mesh already saves to an external resource, no action will be taken. " ) ) ;
2021-03-19 13:57:52 +01:00
} else {
2021-08-09 22:13:42 +02:00
item - > set_metadata ( 0 , E . key ) ;
2021-03-19 13:57:52 +01:00
item - > set_editable ( 0 , true ) ;
item - > set_checked ( 0 , true ) ;
2022-08-30 02:34:01 +02:00
String path = p_path . path_join ( name ) ;
2021-03-19 13:57:52 +01:00
if ( external_extension_type - > get_selected ( ) = = 0 ) {
path + = " .tres " ;
} else {
path + = " .res " ;
}
item - > set_text ( 1 , path ) ;
if ( FileAccess : : exists ( path ) ) {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " Warning: File exists " ) ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 2 , TTR ( " Existing file with the same name will be replaced on import. " ) ) ;
2023-08-13 02:33:39 +02:00
item - > set_icon ( 2 , get_editor_theme_icon ( SNAME ( " StatusWarning " ) ) ) ;
2021-03-19 13:57:52 +01:00
} else {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " Will save to new file " ) ) ;
2023-08-13 02:33:39 +02:00
item - > set_icon ( 2 , get_editor_theme_icon ( SNAME ( " StatusSuccess " ) ) ) ;
2021-03-19 13:57:52 +01:00
}
2023-08-13 02:33:39 +02:00
item - > add_button ( 1 , get_editor_theme_icon ( SNAME ( " Folder " ) ) ) ;
2021-03-19 13:57:52 +01:00
}
} else {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " No import ID " ) ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 2 , TTR ( " Mesh has no name nor any other way to identify on re-import. \n Please name it or ensure it is exported with an unique ID. " ) ) ;
2023-08-13 02:33:39 +02:00
item - > set_icon ( 2 , get_editor_theme_icon ( SNAME ( " StatusError " ) ) ) ;
2021-03-19 13:57:52 +01:00
}
save_path_items . push_back ( item ) ;
}
external_paths - > set_title ( TTR ( " Set paths to save meshes as resource files on Reimport " ) ) ;
2022-07-08 02:31:19 +02:00
external_paths - > set_ok_button_text ( TTR ( " Set Paths " ) ) ;
2021-03-19 13:57:52 +01:00
} break ;
case ACTION_CHOOSE_ANIMATION_SAVE_PATHS : {
2021-08-09 22:13:42 +02:00
for ( const KeyValue < String , AnimationData > & E : animation_map ) {
AnimationData & ad = animation_map [ E . key ] ;
2021-03-19 13:57:52 +01:00
TreeItem * item = external_path_tree - > create_item ( root ) ;
String name = ad . scene_node - > get_text ( 0 ) ;
item - > set_cell_mode ( 0 , TreeItem : : CELL_MODE_CHECK ) ;
2023-08-13 02:33:39 +02:00
item - > set_icon ( 0 , get_editor_theme_icon ( SNAME ( " Animation " ) ) ) ;
2021-03-19 13:57:52 +01:00
item - > set_text ( 0 , name ) ;
if ( ad . settings . has ( " save_to_file/enabled " ) & & bool ( ad . settings [ " save_to_file/enabled " ] ) ) {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " Already Saving " ) ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 2 , TTR ( " This animation already saves to an external resource, no action will be taken. " ) ) ;
2021-03-19 13:57:52 +01:00
} else {
2021-08-09 22:13:42 +02:00
item - > set_metadata ( 0 , E . key ) ;
2021-03-19 13:57:52 +01:00
item - > set_editable ( 0 , true ) ;
item - > set_checked ( 0 , true ) ;
2022-08-30 02:34:01 +02:00
String path = p_path . path_join ( name ) ;
2021-03-19 13:57:52 +01:00
if ( external_extension_type - > get_selected ( ) = = 0 ) {
path + = " .tres " ;
} else {
path + = " .res " ;
}
item - > set_text ( 1 , path ) ;
if ( FileAccess : : exists ( path ) ) {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " Warning: File exists " ) ) ;
2022-08-29 15:55:49 +02:00
item - > set_tooltip_text ( 2 , TTR ( " Existing file with the same name will be replaced on import. " ) ) ;
2023-08-13 02:33:39 +02:00
item - > set_icon ( 2 , get_editor_theme_icon ( SNAME ( " StatusWarning " ) ) ) ;
2021-03-19 13:57:52 +01:00
} else {
2023-03-27 12:06:07 +02:00
item - > set_text ( 2 , TTR ( " Will save to new file " ) ) ;
2023-08-13 02:33:39 +02:00
item - > set_icon ( 2 , get_editor_theme_icon ( SNAME ( " StatusSuccess " ) ) ) ;
2021-03-19 13:57:52 +01:00
}
2023-08-13 02:33:39 +02:00
item - > add_button ( 1 , get_editor_theme_icon ( SNAME ( " Folder " ) ) ) ;
2021-03-19 13:57:52 +01:00
}
save_path_items . push_back ( item ) ;
}
external_paths - > set_title ( TTR ( " Set paths to save animations as resource files on Reimport " ) ) ;
2022-07-08 02:31:19 +02:00
external_paths - > set_ok_button_text ( TTR ( " Set Paths " ) ) ;
2021-03-19 13:57:52 +01:00
} break ;
}
external_paths - > popup_centered_ratio ( ) ;
}
2023-10-06 09:00:36 +02:00
void SceneImportSettingsDialog : : _save_dir_confirm ( ) {
2021-03-19 13:57:52 +01:00
for ( int i = 0 ; i < save_path_items . size ( ) ; i + + ) {
TreeItem * item = save_path_items [ i ] ;
if ( ! item - > is_checked ( 0 ) ) {
continue ; //ignore
}
String path = item - > get_text ( 1 ) ;
if ( ! path . is_resource_file ( ) ) {
continue ;
}
String id = item - > get_metadata ( 0 ) ;
switch ( current_action ) {
case ACTION_EXTRACT_MATERIALS : {
ERR_CONTINUE ( ! material_map . has ( id ) ) ;
MaterialData & md = material_map [ id ] ;
2022-06-03 01:33:42 +02:00
Error err = ResourceSaver : : save ( md . material , path ) ;
2021-03-19 13:57:52 +01:00
if ( err ! = OK ) {
EditorNode : : get_singleton ( ) - > add_io_error ( TTR ( " Can't make material external to file, write error: " ) + " \n \t " + path ) ;
continue ;
}
md . settings [ " use_external/enabled " ] = true ;
md . settings [ " use_external/path " ] = path ;
} break ;
case ACTION_CHOOSE_MESH_SAVE_PATHS : {
ERR_CONTINUE ( ! mesh_map . has ( id ) ) ;
MeshData & md = mesh_map [ id ] ;
md . settings [ " save_to_file/enabled " ] = true ;
md . settings [ " save_to_file/path " ] = path ;
} break ;
case ACTION_CHOOSE_ANIMATION_SAVE_PATHS : {
ERR_CONTINUE ( ! animation_map . has ( id ) ) ;
AnimationData & ad = animation_map [ id ] ;
ad . settings [ " save_to_file/enabled " ] = true ;
ad . settings [ " save_to_file/path " ] = path ;
} break ;
}
}
if ( current_action = = ACTION_EXTRACT_MATERIALS ) {
//as this happens right now, the scene needs to be saved and reimported.
_re_import ( ) ;
open_settings ( base_path ) ;
} else {
scene_import_settings_data - > notify_property_list_changed ( ) ;
}
}
2023-10-06 09:00:36 +02:00
SceneImportSettingsDialog : : SceneImportSettingsDialog ( ) {
2021-03-19 13:57:52 +01:00
singleton = this ;
VBoxContainer * main_vb = memnew ( VBoxContainer ) ;
add_child ( main_vb ) ;
HBoxContainer * menu_hb = memnew ( HBoxContainer ) ;
main_vb - > add_child ( menu_hb ) ;
action_menu = memnew ( MenuButton ) ;
action_menu - > set_text ( TTR ( " Actions... " ) ) ;
2023-01-17 22:27:06 +01:00
// Style the MenuButton like a regular Button to make it more noticeable.
action_menu - > set_flat ( false ) ;
action_menu - > set_focus_mode ( Control : : FOCUS_ALL ) ;
2021-03-19 13:57:52 +01:00
menu_hb - > add_child ( action_menu ) ;
action_menu - > get_popup ( ) - > add_item ( TTR ( " Extract Materials " ) , ACTION_EXTRACT_MATERIALS ) ;
action_menu - > get_popup ( ) - > add_separator ( ) ;
action_menu - > get_popup ( ) - > add_item ( TTR ( " Set Animation Save Paths " ) , ACTION_CHOOSE_ANIMATION_SAVE_PATHS ) ;
action_menu - > get_popup ( ) - > add_item ( TTR ( " Set Mesh Save Paths " ) , ACTION_CHOOSE_MESH_SAVE_PATHS ) ;
2023-10-06 09:00:36 +02:00
action_menu - > get_popup ( ) - > connect ( " id_pressed " , callable_mp ( this , & SceneImportSettingsDialog : : _menu_callback ) ) ;
2021-03-19 13:57:52 +01:00
tree_split = memnew ( HSplitContainer ) ;
main_vb - > add_child ( tree_split ) ;
tree_split - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
data_mode = memnew ( TabContainer ) ;
tree_split - > add_child ( data_mode ) ;
data_mode - > set_custom_minimum_size ( Size2 ( 300 * EDSCALE , 0 ) ) ;
2022-05-27 04:12:09 +02:00
data_mode - > set_theme_type_variation ( " TabContainerOdd " ) ;
2021-03-19 13:57:52 +01:00
property_split = memnew ( HSplitContainer ) ;
tree_split - > add_child ( property_split ) ;
property_split - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
scene_tree = memnew ( Tree ) ;
scene_tree - > set_name ( TTR ( " Scene " ) ) ;
data_mode - > add_child ( scene_tree ) ;
2023-10-06 09:00:36 +02:00
scene_tree - > connect ( " cell_selected " , callable_mp ( this , & SceneImportSettingsDialog : : _scene_tree_selected ) ) ;
2021-03-19 13:57:52 +01:00
mesh_tree = memnew ( Tree ) ;
mesh_tree - > set_name ( TTR ( " Meshes " ) ) ;
data_mode - > add_child ( mesh_tree ) ;
mesh_tree - > set_hide_root ( true ) ;
2023-10-06 09:00:36 +02:00
mesh_tree - > connect ( " cell_selected " , callable_mp ( this , & SceneImportSettingsDialog : : _mesh_tree_selected ) ) ;
2021-03-19 13:57:52 +01:00
material_tree = memnew ( Tree ) ;
material_tree - > set_name ( TTR ( " Materials " ) ) ;
data_mode - > add_child ( material_tree ) ;
2023-10-06 09:00:36 +02:00
material_tree - > connect ( " cell_selected " , callable_mp ( this , & SceneImportSettingsDialog : : _material_tree_selected ) ) ;
2021-03-19 13:57:52 +01:00
material_tree - > set_hide_root ( true ) ;
2023-04-23 13:53:45 +02:00
VBoxContainer * vp_vb = memnew ( VBoxContainer ) ;
vp_vb - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
vp_vb - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
vp_vb - > set_anchors_and_offsets_preset ( Control : : LayoutPreset : : PRESET_FULL_RECT ) ;
property_split - > add_child ( vp_vb ) ;
2021-03-19 13:57:52 +01:00
SubViewportContainer * vp_container = memnew ( SubViewportContainer ) ;
2023-04-23 13:53:45 +02:00
vp_container - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2021-03-19 13:57:52 +01:00
vp_container - > set_custom_minimum_size ( Size2 ( 10 , 10 ) ) ;
vp_container - > set_stretch ( true ) ;
2023-10-06 09:00:36 +02:00
vp_container - > connect ( " gui_input " , callable_mp ( this , & SceneImportSettingsDialog : : _viewport_input ) ) ;
2023-04-23 13:53:45 +02:00
vp_vb - > add_child ( vp_container ) ;
2021-03-19 13:57:52 +01:00
base_viewport = memnew ( SubViewport ) ;
vp_container - > add_child ( base_viewport ) ;
2023-04-23 13:53:45 +02:00
animation_preview = memnew ( PanelContainer ) ;
animation_preview - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
vp_vb - > add_child ( animation_preview ) ;
animation_preview - > hide ( ) ;
HBoxContainer * animation_hbox = memnew ( HBoxContainer ) ;
animation_preview - > add_child ( animation_hbox ) ;
animation_play_button = memnew ( Button ) ;
animation_hbox - > add_child ( animation_play_button ) ;
animation_play_button - > set_flat ( true ) ;
animation_play_button - > set_focus_mode ( Control : : FOCUS_NONE ) ;
animation_play_button - > set_shortcut ( ED_SHORTCUT ( " scene_import_settings/play_selected_animation " , TTR ( " Selected Animation Play/Pause " ) , Key : : SPACE ) ) ;
2023-10-06 09:00:36 +02:00
animation_play_button - > connect ( SNAME ( " pressed " ) , callable_mp ( this , & SceneImportSettingsDialog : : _play_animation ) ) ;
2023-04-23 13:53:45 +02:00
animation_stop_button = memnew ( Button ) ;
animation_hbox - > add_child ( animation_stop_button ) ;
animation_stop_button - > set_flat ( true ) ;
animation_stop_button - > set_focus_mode ( Control : : FOCUS_NONE ) ;
2023-10-06 09:00:36 +02:00
animation_stop_button - > connect ( SNAME ( " pressed " ) , callable_mp ( this , & SceneImportSettingsDialog : : _stop_current_animation ) ) ;
2023-04-23 13:53:45 +02:00
animation_slider = memnew ( HSlider ) ;
animation_hbox - > add_child ( animation_slider ) ;
animation_slider - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
animation_slider - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
animation_slider - > set_max ( 1.0 ) ;
animation_slider - > set_step ( 1.0 / 100.0 ) ;
animation_slider - > set_value_no_signal ( 0.0 ) ;
animation_slider - > set_focus_mode ( Control : : FOCUS_NONE ) ;
2023-10-06 09:00:36 +02:00
animation_slider - > connect ( SNAME ( " value_changed " ) , callable_mp ( this , & SceneImportSettingsDialog : : _animation_slider_value_changed ) ) ;
2023-04-23 13:53:45 +02:00
2021-03-19 13:57:52 +01:00
base_viewport - > set_use_own_world_3d ( true ) ;
camera = memnew ( Camera3D ) ;
base_viewport - > add_child ( camera ) ;
camera - > make_current ( ) ;
2022-08-01 01:20:24 +02:00
if ( GLOBAL_GET ( " rendering/lights_and_shadows/use_physical_light_units " ) ) {
camera_attributes . instantiate ( ) ;
camera - > set_attributes ( camera_attributes ) ;
}
2021-03-19 13:57:52 +01:00
light = memnew ( DirectionalLight3D ) ;
2020-10-17 07:08:21 +02:00
light - > set_transform ( Transform3D ( ) . looking_at ( Vector3 ( - 1 , - 2 , - 0.6 ) , Vector3 ( 0 , 1 , 0 ) ) ) ;
2021-03-19 13:57:52 +01:00
base_viewport - > add_child ( light ) ;
light - > set_shadow ( true ) ;
{
Ref < StandardMaterial3D > selection_mat ;
2021-06-18 00:03:09 +02:00
selection_mat . instantiate ( ) ;
2021-03-19 13:57:52 +01:00
selection_mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
2023-09-27 00:45:57 +02:00
selection_mat - > set_flag ( StandardMaterial3D : : FLAG_DISABLE_FOG , true ) ;
2021-03-19 13:57:52 +01:00
selection_mat - > set_albedo ( Color ( 1 , 0.8 , 1.0 ) ) ;
Ref < SurfaceTool > st ;
2021-06-18 00:03:09 +02:00
st . instantiate ( ) ;
2021-03-19 13:57:52 +01:00
st - > begin ( Mesh : : PRIMITIVE_LINES ) ;
AABB base_aabb ;
base_aabb . size = Vector3 ( 1 , 1 , 1 ) ;
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
base_aabb . get_edge ( i , a , b ) ;
st - > add_vertex ( a ) ;
st - > add_vertex ( a . lerp ( b , 0.2 ) ) ;
st - > add_vertex ( b ) ;
st - > add_vertex ( b . lerp ( a , 0.2 ) ) ;
}
2021-06-18 00:03:09 +02:00
selection_mesh . instantiate ( ) ;
2021-03-19 13:57:52 +01:00
st - > commit ( selection_mesh ) ;
selection_mesh - > surface_set_material ( 0 , selection_mat ) ;
node_selected = memnew ( MeshInstance3D ) ;
node_selected - > set_mesh ( selection_mesh ) ;
2023-09-23 15:18:57 +02:00
node_selected - > set_cast_shadows_setting ( GeometryInstance3D : : SHADOW_CASTING_SETTING_OFF ) ;
2021-03-19 13:57:52 +01:00
base_viewport - > add_child ( node_selected ) ;
node_selected - > hide ( ) ;
}
{
mesh_preview = memnew ( MeshInstance3D ) ;
base_viewport - > add_child ( mesh_preview ) ;
mesh_preview - > hide ( ) ;
2021-06-18 00:03:09 +02:00
material_preview . instantiate ( ) ;
2021-03-19 13:57:52 +01:00
}
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
{
collider_mat . instantiate ( ) ;
collider_mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
2023-09-27 00:45:57 +02:00
collider_mat - > set_flag ( StandardMaterial3D : : FLAG_DISABLE_FOG , true ) ;
Improve collision generation usability in the new 3D scene import workflow.
With this PR it's possible to add a collision during the Mesh import, directly in editor.
To generate the shape is possible to chose between the following options:
- Decompose Convex: The Mesh is decomposed in one or many Convex Shapes (Using the VHACD library).
- Simple Convex: Is generated a convex shape that enclose the entire mesh.
- Trimesh: Generate a trimesh shape using the Mesh faces.
- Box: Add a primitive box shape, where you can tweak the `size`, `position`, `rotation`.
- Sphere: Add a primitive sphere shape, where you can tweak the `radius`, `position`, `rotation`.
- Cylinder: Add a primitive cylinder shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
- Capsule: Add a primitive capsule shape, where you can tweak the `height`, `radius`, `position`, `rotation`.
It's also possible to chose the generated body, so you can create:
- Rigid Body
- Static Body
- Area
2021-08-22 18:19:13 +02:00
collider_mat - > set_albedo ( Color ( 0.5 , 0.5 , 1.0 ) ) ;
}
2021-03-19 13:57:52 +01:00
inspector = memnew ( EditorInspector ) ;
inspector - > set_custom_minimum_size ( Size2 ( 300 * EDSCALE , 0 ) ) ;
2023-10-06 09:00:36 +02:00
inspector - > connect ( SNAME ( " property_edited " ) , callable_mp ( this , & SceneImportSettingsDialog : : _inspector_property_edited ) ) ;
2021-03-19 13:57:52 +01:00
property_split - > add_child ( inspector ) ;
scene_import_settings_data = memnew ( SceneImportSettingsData ) ;
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Reimport " ) ) ;
set_cancel_button_text ( TTR ( " Close " ) ) ;
2021-03-19 13:57:52 +01:00
external_paths = memnew ( ConfirmationDialog ) ;
add_child ( external_paths ) ;
external_path_tree = memnew ( Tree ) ;
external_paths - > add_child ( external_path_tree ) ;
2023-10-06 09:00:36 +02:00
external_path_tree - > connect ( " button_clicked " , callable_mp ( this , & SceneImportSettingsDialog : : _browse_save_callback ) ) ;
external_paths - > connect ( " confirmed " , callable_mp ( this , & SceneImportSettingsDialog : : _save_dir_confirm ) ) ;
2021-03-19 13:57:52 +01:00
external_path_tree - > set_columns ( 3 ) ;
external_path_tree - > set_column_titles_visible ( true ) ;
external_path_tree - > set_column_expand ( 0 , true ) ;
2021-06-28 15:40:56 +02:00
external_path_tree - > set_column_custom_minimum_width ( 0 , 100 * EDSCALE ) ;
2021-03-19 13:57:52 +01:00
external_path_tree - > set_column_title ( 0 , TTR ( " Resource " ) ) ;
external_path_tree - > set_column_expand ( 1 , true ) ;
2021-06-28 15:40:56 +02:00
external_path_tree - > set_column_custom_minimum_width ( 1 , 100 * EDSCALE ) ;
2021-03-19 13:57:52 +01:00
external_path_tree - > set_column_title ( 1 , TTR ( " Path " ) ) ;
external_path_tree - > set_column_expand ( 2 , false ) ;
2021-06-28 15:40:56 +02:00
external_path_tree - > set_column_custom_minimum_width ( 2 , 200 * EDSCALE ) ;
2021-03-19 13:57:52 +01:00
external_path_tree - > set_column_title ( 2 , TTR ( " Status " ) ) ;
save_path = memnew ( EditorFileDialog ) ;
save_path - > set_file_mode ( EditorFileDialog : : FILE_MODE_OPEN_DIR ) ;
HBoxContainer * extension_hb = memnew ( HBoxContainer ) ;
save_path - > get_vbox ( ) - > add_child ( extension_hb ) ;
extension_hb - > add_spacer ( ) ;
2022-06-08 11:42:51 +02:00
extension_hb - > add_child ( memnew ( Label ( TTR ( " Save Extension: " ) ) ) ) ;
2021-03-19 13:57:52 +01:00
external_extension_type = memnew ( OptionButton ) ;
extension_hb - > add_child ( external_extension_type ) ;
external_extension_type - > add_item ( TTR ( " Text: *.tres " ) ) ;
external_extension_type - > add_item ( TTR ( " Binary: *.res " ) ) ;
external_path_tree - > set_hide_root ( true ) ;
add_child ( save_path ) ;
item_save_path = memnew ( EditorFileDialog ) ;
item_save_path - > set_file_mode ( EditorFileDialog : : FILE_MODE_SAVE_FILE ) ;
2022-07-04 23:26:26 +02:00
item_save_path - > add_filter ( " *.tres " , TTR ( " Text Resource " ) ) ;
item_save_path - > add_filter ( " *.res " , TTR ( " Binary Resource " ) ) ;
2021-03-19 13:57:52 +01:00
add_child ( item_save_path ) ;
2023-10-06 09:00:36 +02:00
item_save_path - > connect ( " file_selected " , callable_mp ( this , & SceneImportSettingsDialog : : _save_path_changed ) ) ;
2021-03-19 13:57:52 +01:00
2023-10-06 09:00:36 +02:00
save_path - > connect ( " dir_selected " , callable_mp ( this , & SceneImportSettingsDialog : : _save_dir_callback ) ) ;
2022-04-12 16:07:09 +02:00
update_view_timer = memnew ( Timer ) ;
update_view_timer - > set_wait_time ( 0.2 ) ;
2023-10-06 09:00:36 +02:00
update_view_timer - > connect ( " timeout " , callable_mp ( this , & SceneImportSettingsDialog : : _update_view_gizmos ) ) ;
2022-04-12 16:07:09 +02:00
add_child ( update_view_timer ) ;
2021-03-19 13:57:52 +01:00
}
2023-10-06 09:00:36 +02:00
SceneImportSettingsDialog : : ~ SceneImportSettingsDialog ( ) {
2021-03-19 13:57:52 +01:00
memdelete ( scene_import_settings_data ) ;
}