diff options
Diffstat (limited to 'editor/import/resource_importer_scene.cpp')
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index fc4f673ec4..5abae339df 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -119,6 +119,304 @@ void EditorSceneImporter::_bind_methods() { BIND_CONSTANT(IMPORT_USE_COMPRESSION); } +//////////////////////////////////////////////// + +void EditorSceneImporterMesh::add_blend_shape(const String &p_name) { + ERR_FAIL_COND(surfaces.size() > 0); + blend_shapes.push_back(p_name); +} + +int EditorSceneImporterMesh::get_blend_shape_count() const { + return blend_shapes.size(); +} + +String EditorSceneImporterMesh::get_blend_shape_name(int p_blend_shape) const { + ERR_FAIL_INDEX_V(p_blend_shape, blend_shapes.size(), String()); + return blend_shapes[p_blend_shape]; +} + +void EditorSceneImporterMesh::set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode) { + blend_shape_mode = p_blend_shape_mode; +} +Mesh::BlendShapeMode EditorSceneImporterMesh::get_blend_shape_mode() const { + return blend_shape_mode; +} + +void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name) { + ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size()); + ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX); + Surface s; + s.primitive = p_primitive; + s.arrays = p_arrays; + s.name = p_name; + + for (int i = 0; i < blend_shapes.size(); i++) { + Array bsdata = p_blend_shapes[i]; + ERR_FAIL_COND(bsdata.size() != Mesh::ARRAY_MAX); + Surface::BlendShape bs; + bs.arrays = bsdata; + s.blend_shape_data.push_back(bs); + } + + List<Variant> lods; + p_lods.get_key_list(&lods); + for (List<Variant>::Element *E = lods.front(); E; E = E->next()) { + ERR_CONTINUE(!E->get().is_num()); + Surface::LOD lod; + lod.distance = E->get(); + lod.indices = p_lods[E->get()]; + ERR_CONTINUE(lod.indices.size() == 0); + s.lods.push_back(lod); + } + + s.material = p_material; + + surfaces.push_back(s); + mesh.unref(); +} +int EditorSceneImporterMesh::get_surface_count() const { + return surfaces.size(); +} + +Mesh::PrimitiveType EditorSceneImporterMesh::get_surface_primitive_type(int p_surface) { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Mesh::PRIMITIVE_MAX); + return surfaces[p_surface].primitive; +} +Array EditorSceneImporterMesh::get_surface_arrays(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); + return surfaces[p_surface].arrays; +} +String EditorSceneImporterMesh::get_surface_name(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), String()); + return surfaces[p_surface].name; +} +Array EditorSceneImporterMesh::get_surface_blend_shape_arrays(int p_surface, int p_blend_shape) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); + ERR_FAIL_INDEX_V(p_blend_shape, surfaces[p_surface].blend_shape_data.size(), Array()); + return surfaces[p_surface].blend_shape_data[p_blend_shape].arrays; +} +int EditorSceneImporterMesh::get_surface_lod_count(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); + return surfaces[p_surface].lods.size(); +} +Vector<int> EditorSceneImporterMesh::get_surface_lod_indices(int p_surface, int p_lod) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Vector<int>()); + ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), Vector<int>()); + + return surfaces[p_surface].lods[p_lod].indices; +} + +float EditorSceneImporterMesh::get_surface_lod_size(int p_surface, int p_lod) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); + ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), 0); + return surfaces[p_surface].lods[p_lod].distance; +} + +Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Ref<Material>()); + return surfaces[p_surface].material; +} + +bool EditorSceneImporterMesh::has_mesh() const { + return mesh.is_valid(); +} + +Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh() { + ERR_FAIL_COND_V(surfaces.size() == 0, Ref<ArrayMesh>()); + + if (mesh.is_null()) { + mesh.instance(); + for (int i = 0; i < blend_shapes.size(); i++) { + mesh->add_blend_shape(blend_shapes[i]); + } + mesh->set_blend_shape_mode(blend_shape_mode); + for (int i = 0; i < surfaces.size(); i++) { + Array bs_data; + if (surfaces[i].blend_shape_data.size()) { + for (int j = 0; j < surfaces[i].blend_shape_data.size(); j++) { + bs_data.push_back(surfaces[i].blend_shape_data[j].arrays); + } + } + Dictionary lods; + if (surfaces[i].lods.size()) { + for (int j = 0; j < surfaces[i].lods.size(); j++) { + lods[surfaces[i].lods[j].distance] = surfaces[i].lods[j].indices; + } + } + + mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods); + if (surfaces[i].material.is_valid()) { + mesh->surface_set_material(mesh->get_surface_count() - 1, surfaces[i].material); + } + if (surfaces[i].name != String()) { + mesh->surface_set_name(mesh->get_surface_count() - 1, surfaces[i].name); + } + } + } + + return mesh; +} + +void EditorSceneImporterMesh::clear() { + surfaces.clear(); + blend_shapes.clear(); + mesh.unref(); +} + +void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) { + clear(); + if (p_data.has("blend_shape_names")) { + blend_shapes = p_data["blend_shape_names"]; + } + if (p_data.has("surfaces")) { + Array surface_arr = p_data["surfaces"]; + for (int i = 0; i < surface_arr.size(); i++) { + Dictionary s = surface_arr[i]; + ERR_CONTINUE(!s.has("primitive")); + ERR_CONTINUE(!s.has("arrays")); + Mesh::PrimitiveType prim = Mesh::PrimitiveType(int(s["primitive"])); + ERR_CONTINUE(prim >= Mesh::PRIMITIVE_MAX); + Array arr = s["arrays"]; + Dictionary lods; + String name; + if (s.has("name")) { + name = s["name"]; + } + if (s.has("lods")) { + lods = s["lods"]; + } + Array blend_shapes; + if (s.has("blend_shapes")) { + blend_shapes = s["blend_shapes"]; + } + Ref<Material> material; + if (s.has("material")) { + material = s["material"]; + } + add_surface(prim, arr, blend_shapes, lods, material, name); + } + } +} +Dictionary EditorSceneImporterMesh::_get_data() const { + Dictionary data; + if (blend_shapes.size()) { + data["blend_shape_names"] = blend_shapes; + } + Array surface_arr; + for (int i = 0; i < surfaces.size(); i++) { + Dictionary d; + d["primitive"] = surfaces[i].primitive; + d["arrays"] = surfaces[i].arrays; + if (surfaces[i].blend_shape_data.size()) { + Array bs_data; + for (int j = 0; j < surfaces[i].blend_shape_data.size(); j++) { + bs_data.push_back(surfaces[i].blend_shape_data[j].arrays); + } + d["blend_shapes"] = bs_data; + } + if (surfaces[i].lods.size()) { + Dictionary lods; + for (int j = 0; j < surfaces[i].lods.size(); j++) { + lods[surfaces[i].lods[j].distance] = surfaces[i].lods[j].indices; + } + d["lods"] = lods; + } + + if (surfaces[i].material.is_valid()) { + d["material"] = surfaces[i].material; + } + + if (surfaces[i].name != String()) { + d["name"] = surfaces[i].name; + } + + surface_arr.push_back(d); + } + data["surfaces"] = surface_arr; + return data; +} + +void EditorSceneImporterMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &EditorSceneImporterMesh::add_blend_shape); + ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &EditorSceneImporterMesh::get_blend_shape_count); + ClassDB::bind_method(D_METHOD("get_blend_shape_name", "blend_shape_idx"), &EditorSceneImporterMesh::get_blend_shape_name); + + ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &EditorSceneImporterMesh::set_blend_shape_mode); + ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &EditorSceneImporterMesh::get_blend_shape_mode); + + ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String())); + + ClassDB::bind_method(D_METHOD("get_surface_count"), &EditorSceneImporterMesh::get_surface_count); + ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &EditorSceneImporterMesh::get_surface_primitive_type); + ClassDB::bind_method(D_METHOD("get_surface_name", "surface_idx"), &EditorSceneImporterMesh::get_surface_name); + ClassDB::bind_method(D_METHOD("get_surface_arrays", "surface_idx"), &EditorSceneImporterMesh::get_surface_arrays); + ClassDB::bind_method(D_METHOD("get_surface_blend_shape_arrays", "surface_idx", "blend_shape_idx"), &EditorSceneImporterMesh::get_surface_blend_shape_arrays); + ClassDB::bind_method(D_METHOD("get_surface_lod_count", "surface_idx"), &EditorSceneImporterMesh::get_surface_lod_count); + ClassDB::bind_method(D_METHOD("get_surface_lod_size", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_size); + ClassDB::bind_method(D_METHOD("get_surface_lod_indices", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_indices); + ClassDB::bind_method(D_METHOD("get_surface_material", "surface_idx"), &EditorSceneImporterMesh::get_surface_material); + + ClassDB::bind_method(D_METHOD("get_mesh"), &EditorSceneImporterMesh::get_mesh); + ClassDB::bind_method(D_METHOD("clear"), &EditorSceneImporterMesh::clear); + + ClassDB::bind_method(D_METHOD("_set_data", "data"), &EditorSceneImporterMesh::_set_data); + ClassDB::bind_method(D_METHOD("_get_data"), &EditorSceneImporterMesh::_get_data); + + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); +} + +void EditorSceneImporterMeshNode::set_mesh(const Ref<EditorSceneImporterMesh> &p_mesh) { + mesh = p_mesh; +} +Ref<EditorSceneImporterMesh> EditorSceneImporterMeshNode::get_mesh() const { + return mesh; +} + +void EditorSceneImporterMeshNode::set_skin(const Ref<Skin> &p_skin) { + skin = p_skin; +} +Ref<Skin> EditorSceneImporterMeshNode::get_skin() const { + return skin; +} + +void EditorSceneImporterMeshNode::set_surface_material(int p_idx, const Ref<Material> &p_material) { + ERR_FAIL_COND(p_idx < 0); + if (p_idx >= surface_materials.size()) { + surface_materials.resize(p_idx + 1); + } + + surface_materials.write[p_idx] = p_material; +} +Ref<Material> EditorSceneImporterMeshNode::get_surface_material(int p_idx) const { + ERR_FAIL_COND_V(p_idx < 0, Ref<Material>()); + if (p_idx >= surface_materials.size()) { + return Ref<Material>(); + } + return surface_materials[p_idx]; +} + +void EditorSceneImporterMeshNode::set_skeleton_path(const NodePath &p_path) { + skeleton_path = p_path; +} +NodePath EditorSceneImporterMeshNode::get_skeleton_path() const { + return skeleton_path; +} + +void EditorSceneImporterMeshNode::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &EditorSceneImporterMeshNode::set_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &EditorSceneImporterMeshNode::get_mesh); + + ClassDB::bind_method(D_METHOD("set_skin", "skin"), &EditorSceneImporterMeshNode::set_skin); + ClassDB::bind_method(D_METHOD("get_skin"), &EditorSceneImporterMeshNode::get_skin); + + ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &EditorSceneImporterMeshNode::set_skeleton_path); + ClassDB::bind_method(D_METHOD("get_skeleton_path"), &EditorSceneImporterMeshNode::get_skeleton_path); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "EditorSceneImporterMesh"), "set_mesh", "get_mesh"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path"); +} + ///////////////////////////////// void EditorScenePostImport::_bind_methods() { BIND_VMETHOD(MethodInfo(Variant::OBJECT, "post_import", PropertyInfo(Variant::OBJECT, "scene"))); @@ -1219,6 +1517,34 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito return importer->import_animation(p_path, p_flags, p_bake_fps); } +void ResourceImporterScene::_generate_meshes(Node *p_node) { + EditorSceneImporterMeshNode *src_mesh = Object::cast_to<EditorSceneImporterMeshNode>(p_node); + if (src_mesh != nullptr) { + //is mesh + MeshInstance3D *mesh_node = memnew(MeshInstance3D); + mesh_node->set_transform(src_mesh->get_transform()); + mesh_node->set_skin(src_mesh->get_skin()); + mesh_node->set_skeleton_path(src_mesh->get_skeleton_path()); + + Ref<ArrayMesh> mesh; + if (!src_mesh->get_mesh()->has_mesh()) { + //do mesh processing + } + mesh = src_mesh->get_mesh()->get_mesh(); + mesh_node->set_mesh(mesh); + for (int i = 0; i < mesh->get_surface_count(); i++) { + mesh_node->set_surface_material(i, src_mesh->get_surface_material(i)); + } + + p_node->replace_by(mesh_node); + memdelete(p_node); + p_node = mesh_node; + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _generate_meshes(p_node->get_child(i)); + } +} Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { const String &src_path = p_source_file; @@ -1315,6 +1641,8 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p scene->set_name(p_save_path.get_file().get_basename()); } + _generate_meshes(scene); + err = OK; String animation_filter = String(p_options["animation/filter_script"]).strip_edges(); |