@@ -1368,6 +1368,51 @@ Node *ResourceImporterScene::_post_fix_animations(Node *p_node, Node *p_root, co
1368
1368
return p_node;
1369
1369
}
1370
1370
1371
+ Node *ResourceImporterScene::_replace_node_with_type_and_script (Node *p_node, String p_node_type, Ref<Script> p_script) {
1372
+ p_node_type = p_node_type.get_slicec (' ' , 0 ); // Full root_type is "ClassName (filename.gd)" for a script global class.
1373
+ if (p_script.is_valid ()) {
1374
+ // Ensure the node type supports the script, or pick one that does.
1375
+ String script_base_type = p_script->get_instance_base_type ();
1376
+ if (ClassDB::is_parent_class (script_base_type, " Node" )) {
1377
+ if (p_node_type.is_empty () || !ClassDB::is_parent_class (p_node_type, script_base_type)) {
1378
+ p_node_type = script_base_type;
1379
+ }
1380
+ }
1381
+ }
1382
+ if (!p_node_type.is_empty () && ScriptServer::is_global_class (p_node_type)) {
1383
+ // If the user specified a script class, we need to get the base node type.
1384
+ if (p_script.is_null ()) {
1385
+ p_script = ResourceLoader::load (ScriptServer::get_global_class_path (p_node_type));
1386
+ }
1387
+ p_node_type = ScriptServer::get_global_class_base (p_node_type);
1388
+ }
1389
+ if (!p_node_type.is_empty () && p_node->get_class_name () != p_node_type) {
1390
+ // If the user specified a Godot node type that does not match
1391
+ // what the scene import gave us, replace the root node.
1392
+ Node *new_base_node = Object::cast_to<Node>(ClassDB::instantiate (p_node_type));
1393
+ if (new_base_node) {
1394
+ List<PropertyInfo> old_properties;
1395
+ p_node->get_property_list (&old_properties);
1396
+ for (const PropertyInfo &prop : old_properties) {
1397
+ if (!(prop.usage & PROPERTY_USAGE_STORAGE)) {
1398
+ continue ;
1399
+ }
1400
+ new_base_node->set (prop.name , p_node->get (prop.name ));
1401
+ }
1402
+ new_base_node->set_name (p_node->get_name ());
1403
+ _copy_meta (p_node, new_base_node);
1404
+ p_node->replace_by (new_base_node);
1405
+ p_node->set_owner (nullptr );
1406
+ memdelete (p_node);
1407
+ p_node = new_base_node;
1408
+ }
1409
+ }
1410
+ if (p_script.is_valid ()) {
1411
+ p_node->set_script (Variant (p_script));
1412
+ }
1413
+ return p_node;
1414
+ }
1415
+
1371
1416
Node *ResourceImporterScene::_post_fix_node (Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps, float p_applied_root_scale, const String &p_source_file, const HashMap<StringName, Variant> &p_options) {
1372
1417
// children first
1373
1418
for (int i = 0 ; i < p_node->get_child_count (); i++) {
@@ -1842,6 +1887,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
1842
1887
}
1843
1888
}
1844
1889
1890
+ String node_type = node_settings.get (" node/node_type" , " " );
1891
+ Ref<Script> node_script = node_settings.get (" node/script" , Ref<Script>());
1892
+ p_node = _replace_node_with_type_and_script (p_node, node_type, node_script);
1893
+
1845
1894
return p_node;
1846
1895
}
1847
1896
@@ -2057,9 +2106,12 @@ void ResourceImporterScene::_compress_animations(AnimationPlayer *anim, int p_pa
2057
2106
void ResourceImporterScene::get_internal_import_options (InternalImportCategory p_category, List<ImportOption> *r_options) const {
2058
2107
switch (p_category) {
2059
2108
case INTERNAL_IMPORT_CATEGORY_NODE: {
2109
+ r_options->push_back (ImportOption (PropertyInfo (Variant::STRING, " node/node_type" , PROPERTY_HINT_TYPE_STRING, " Node" ), " " ));
2110
+ r_options->push_back (ImportOption (PropertyInfo (Variant::OBJECT, " node/script" , PROPERTY_HINT_RESOURCE_TYPE, " Script" ), Variant ()));
2060
2111
r_options->push_back (ImportOption (PropertyInfo (Variant::BOOL, " import/skip_import" , PROPERTY_HINT_NONE, " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false ));
2061
2112
} break ;
2062
2113
case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: {
2114
+ r_options->push_back (ImportOption (PropertyInfo (Variant::OBJECT, " node/script" , PROPERTY_HINT_RESOURCE_TYPE, " Script" ), Variant ()));
2063
2115
r_options->push_back (ImportOption (PropertyInfo (Variant::BOOL, " import/skip_import" , PROPERTY_HINT_NONE, " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false ));
2064
2116
r_options->push_back (ImportOption (PropertyInfo (Variant::BOOL, " generate/physics" , PROPERTY_HINT_NONE, " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false ));
2065
2117
r_options->push_back (ImportOption (PropertyInfo (Variant::INT, " generate/navmesh" , PROPERTY_HINT_ENUM, " Disabled,Mesh + NavMesh,NavMesh Only" ), 0 ));
@@ -2140,6 +2192,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
2140
2192
}
2141
2193
} break ;
2142
2194
case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: {
2195
+ r_options->push_back (ImportOption (PropertyInfo (Variant::OBJECT, " node/script" , PROPERTY_HINT_RESOURCE_TYPE, " Script" ), Variant ()));
2143
2196
r_options->push_back (ImportOption (PropertyInfo (Variant::BOOL, " import/skip_import" , PROPERTY_HINT_NONE, " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false ));
2144
2197
r_options->push_back (ImportOption (PropertyInfo (Variant::BOOL, " optimizer/enabled" , PROPERTY_HINT_NONE, " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true ));
2145
2198
r_options->push_back (ImportOption (PropertyInfo (Variant::FLOAT, " optimizer/max_velocity_error" , PROPERTY_HINT_RANGE, " 0,1,0.01" ), 0.01 ));
@@ -2152,6 +2205,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
2152
2205
r_options->push_back (ImportOption (PropertyInfo (Variant::INT, " import_tracks/scale" , PROPERTY_HINT_ENUM, " IfPresent,IfPresentForAll,Never" ), 1 ));
2153
2206
} break ;
2154
2207
case INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE: {
2208
+ r_options->push_back (ImportOption (PropertyInfo (Variant::OBJECT, " node/script" , PROPERTY_HINT_RESOURCE_TYPE, " Script" ), Variant ()));
2155
2209
r_options->push_back (ImportOption (PropertyInfo (Variant::BOOL, " import/skip_import" , PROPERTY_HINT_NONE, " " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false ));
2156
2210
r_options->push_back (ImportOption (PropertyInfo (Variant::INT, " rest_pose/load_pose" , PROPERTY_HINT_ENUM, " Default Pose,Use AnimationPlayer,Load External Animation" , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0 ));
2157
2211
r_options->push_back (ImportOption (PropertyInfo (Variant::OBJECT, " rest_pose/external_animation_library" , PROPERTY_HINT_RESOURCE_TYPE, " Animation,AnimationLibrary" , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Variant ()));
@@ -2436,6 +2490,7 @@ bool ResourceImporterScene::get_internal_option_update_view_required(InternalImp
2436
2490
void ResourceImporterScene::get_import_options (const String &p_path, List<ImportOption> *r_options, int p_preset) const {
2437
2491
r_options->push_back (ImportOption (PropertyInfo (Variant::STRING, " nodes/root_type" , PROPERTY_HINT_TYPE_STRING, " Node" ), " " ));
2438
2492
r_options->push_back (ImportOption (PropertyInfo (Variant::STRING, " nodes/root_name" ), " " ));
2493
+ r_options->push_back (ImportOption (PropertyInfo (Variant::OBJECT, " nodes/root_script" , PROPERTY_HINT_RESOURCE_TYPE, " Script" ), Variant ()));
2439
2494
2440
2495
List<String> script_extensions;
2441
2496
ResourceLoader::get_recognized_extensions_for_type (" Script" , &script_extensions);
@@ -3147,28 +3202,8 @@ Error ResourceImporterScene::import(ResourceUID::ID p_source_id, const String &p
3147
3202
_post_fix_animations (scene, scene, node_data, animation_data, fps, remove_immutable_tracks);
3148
3203
3149
3204
String root_type = p_options[" nodes/root_type" ];
3150
- if (!root_type.is_empty ()) {
3151
- root_type = root_type.split (" " )[0 ]; // Full root_type is "ClassName (filename.gd)" for a script global class.
3152
- Ref<Script> root_script = nullptr ;
3153
- if (ScriptServer::is_global_class (root_type)) {
3154
- root_script = ResourceLoader::load (ScriptServer::get_global_class_path (root_type));
3155
- root_type = ScriptServer::get_global_class_base (root_type);
3156
- }
3157
- if (scene->get_class_name () != root_type) {
3158
- // If the user specified a Godot node type that does not match
3159
- // what the scene import gave us, replace the root node.
3160
- Node *base_node = Object::cast_to<Node>(ClassDB::instantiate (root_type));
3161
- if (base_node) {
3162
- scene->replace_by (base_node);
3163
- scene->set_owner (nullptr );
3164
- memdelete (scene);
3165
- scene = base_node;
3166
- }
3167
- }
3168
- if (root_script.is_valid ()) {
3169
- scene->set_script (Variant (root_script));
3170
- }
3171
- }
3205
+ Ref<Script> root_script = p_options[" nodes/root_script" ];
3206
+ scene = _replace_node_with_type_and_script (scene, root_type, root_script);
3172
3207
3173
3208
String root_name = p_options[" nodes/root_name" ];
3174
3209
if (!root_name.is_empty () && root_name != " Scene Root" ) {
0 commit comments