summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/import/resource_importer_scene.cpp275
-rw-r--r--editor/import/resource_importer_scene.h2
-rw-r--r--editor/plugins/mesh_instance_editor_plugin.cpp54
3 files changed, 194 insertions, 137 deletions
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index fb2e3c0401..ab515785da 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -279,7 +279,24 @@ static String _fixstr(const String &p_what, const String &p_str) {
return what;
}
-Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<ArrayMesh>, Ref<Shape> > &collision_map, LightBakeMode p_light_bake_mode) {
+static void _gen_shape_list(const Ref<Mesh> &mesh, List<Ref<Shape> > &r_shape_list, bool p_convex) {
+
+ if (!p_convex) {
+
+ Ref<Shape> shape = mesh->create_trimesh_shape();
+ r_shape_list.push_back(shape);
+ } else {
+
+ Vector<Ref<Shape> > cd = mesh->convex_decompose();
+ if (cd.size()) {
+ for (int i = 0; i < cd.size(); i++) {
+ r_shape_list.push_back(cd[i]);
+ }
+ }
+ }
+}
+
+Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape> > > &collision_map, LightBakeMode p_light_bake_mode) {
// children first
for (int i = 0; i < p_node->get_child_count(); i++) {
@@ -365,37 +382,52 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array
return p_node;
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
if (mi) {
- Node *col = NULL;
-
- if (_teststr(name, "colonly")) {
- col = mi->create_trimesh_collision_node();
- if (col == NULL) {
- ERR_PRINTS("Error generating collision for mesh: " + name);
- } else {
-
- col->set_name(_fixstr(name, "colonly"));
+ Ref<Mesh> mesh = mi->get_mesh();
+
+ if (mesh.is_valid()) {
+ List<Ref<Shape> > shapes;
+ String fixed_name;
+ if (collision_map.has(mesh)) {
+ shapes = collision_map[mesh];
+ } else if (_teststr(name, "colonly")) {
+ _gen_shape_list(mesh, shapes, false);
+ collision_map[mesh] = shapes;
+ } else if (_teststr(name, "convcolonly")) {
+ _gen_shape_list(mesh, shapes, true);
+ collision_map[mesh] = shapes;
}
- } else {
- col = mi->create_convex_collision_node();
- if (col == NULL) {
- ERR_PRINTS("Error generating collision for mesh: " + name);
- } else {
- col->set_name(_fixstr(name, "convcolonly"));
+ if (_teststr(name, "colonly")) {
+ fixed_name = _fixstr(name, "colonly");
+ } else if (_teststr(name, "convcolonly")) {
+ fixed_name = _fixstr(name, "convcolonly");
}
- }
- if (col) {
- Object::cast_to<Spatial>(col)->set_transform(mi->get_transform());
- p_node->replace_by(col);
- memdelete(p_node);
- p_node = col;
+ ERR_FAIL_COND_V(fixed_name == String(), NULL);
+
+ if (shapes.size()) {
+
+ StaticBody *col = memnew(StaticBody);
+ col->set_transform(mi->get_transform());
+ col->set_name(fixed_name);
+ p_node->replace_by(col);
+ memdelete(p_node);
+ p_node = col;
+
+ int idx = 0;
+ for (List<Ref<Shape> >::Element *E = shapes.front(); E; E = E->next()) {
+
+ CollisionShape *cshape = memnew(CollisionShape);
+ cshape->set_shape(E->get());
+ col->add_child(cshape);
- StaticBody *sb = Object::cast_to<StaticBody>(col);
- CollisionShape *colshape = Object::cast_to<CollisionShape>(sb->get_child(0));
- colshape->set_name("shape");
- colshape->set_owner(p_node->get_owner());
+ cshape->set_name("shape" + itos(idx));
+ cshape->set_owner(col->get_owner());
+ idx++;
+ }
+ }
}
+
} else if (p_node->has_meta("empty_draw_type")) {
String empty_draw_type = String(p_node->get_meta("empty_draw_type"));
StaticBody *sb = memnew(StaticBody);
@@ -434,77 +466,91 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array
if (isroot)
return p_node;
- // get mesh instance and bounding box
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
- AABB aabb = mi->get_aabb();
-
- // create a new rigid body collision node
- RigidBody *rigid_body = memnew(RigidBody);
- Node *col = rigid_body;
- ERR_FAIL_COND_V(!col, NULL);
-
- // remove node name postfix
- col->set_name(_fixstr(name, "rigid"));
- // get mesh instance xform matrix to the rigid body collision node
- Object::cast_to<Spatial>(col)->set_transform(mi->get_transform());
- // save original node by duplicating it into a new instance and correcting the name
- Node *mesh = p_node->duplicate();
- mesh->set_name(_fixstr(name, "rigid"));
- // reset the xform matrix of the duplicated node so it can inherit parent node xform
- Object::cast_to<Spatial>(mesh)->set_transform(Transform(Basis()));
- // reparent the new mesh node to the rigid body collision node
- p_node->add_child(mesh);
- mesh->set_owner(p_node->get_owner());
- // replace the original node with the rigid body collision node
- p_node->replace_by(col);
- memdelete(p_node);
- p_node = col;
-
- // create an alias for the rigid body collision node
- RigidBody *rb = Object::cast_to<RigidBody>(col);
- // create a new Box collision shape and set the right extents
- Ref<BoxShape> shape = memnew(BoxShape);
- shape->set_extents(aabb.get_size() * 0.5);
- CollisionShape *colshape = memnew(CollisionShape);
- colshape->set_name("shape");
- colshape->set_shape(shape);
- // reparent the new collision shape to the rigid body collision node
- rb->add_child(colshape);
- colshape->set_owner(p_node->get_owner());
+ Ref<Mesh> mesh = mi->get_mesh();
+
+ if (mesh.is_valid()) {
+ List<Ref<Shape> > shapes;
+ if (collision_map.has(mesh)) {
+ shapes = collision_map[mesh];
+ } else {
+ _gen_shape_list(mesh, shapes, true);
+ }
+
+ RigidBody *rigid_body = memnew(RigidBody);
+ rigid_body->set_name(_fixstr(name, "rigid"));
+ p_node->replace_by(rigid_body);
+ rigid_body->set_transform(mi->get_transform());
+ p_node = rigid_body;
+ mi->set_name("mesh");
+ mi->set_transform(Transform());
+ rigid_body->add_child(mi);
+ mi->set_owner(rigid_body->get_owner());
+
+ int idx = 0;
+ for (List<Ref<Shape> >::Element *E = shapes.front(); E; E = E->next()) {
+
+ CollisionShape *cshape = memnew(CollisionShape);
+ cshape->set_shape(E->get());
+ rigid_body->add_child(cshape);
+
+ cshape->set_name("shape" + itos(idx));
+ cshape->set_owner(p_node->get_owner());
+ idx++;
+ }
+ }
} else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<MeshInstance>(p_node)) {
MeshInstance *mi = Object::cast_to<MeshInstance>(p_node);
- Node *col;
- if (_teststr(name, "col")) {
- String new_name = _fixstr(name, "col");
- if (mi->get_parent() && !mi->get_parent()->has_node(new_name)) {
- mi->set_name(new_name);
+ Ref<Mesh> mesh = mi->get_mesh();
+
+ if (mesh.is_valid()) {
+ List<Ref<Shape> > shapes;
+ String fixed_name;
+ if (collision_map.has(mesh)) {
+ shapes = collision_map[mesh];
+ } else if (_teststr(name, "col")) {
+ _gen_shape_list(mesh, shapes, false);
+ collision_map[mesh] = shapes;
+ } else if (_teststr(name, "convcol")) {
+ _gen_shape_list(mesh, shapes, true);
+ collision_map[mesh] = shapes;
}
- col = mi->create_trimesh_collision_node();
- ERR_FAIL_COND_V(!col, NULL);
- col->set_name("col");
- } else {
- String new_name = _fixstr(name, "convcol");
- if (mi->get_parent() && !mi->get_parent()->has_node(new_name)) {
- mi->set_name(new_name);
+ if (_teststr(name, "col")) {
+ fixed_name = _fixstr(name, "col");
+ } else if (_teststr(name, "convcol")) {
+ fixed_name = _fixstr(name, "convcol");
}
- col = mi->create_convex_collision_node();
- ERR_FAIL_COND_V(!col, NULL);
- col->set_name("convcol");
- }
+ if (fixed_name != String()) {
+ if (mi->get_parent() && !mi->get_parent()->has_node(fixed_name)) {
+ mi->set_name(fixed_name);
+ }
+ }
+
+ if (shapes.size()) {
+ StaticBody *col = memnew(StaticBody);
+ col->set_name("static_collision");
+ mi->add_child(col);
+ col->set_owner(mi->get_owner());
- p_node->add_child(col);
+ int idx = 0;
+ for (List<Ref<Shape> >::Element *E = shapes.front(); E; E = E->next()) {
- StaticBody *sb = Object::cast_to<StaticBody>(col);
- CollisionShape *colshape = Object::cast_to<CollisionShape>(sb->get_child(0));
- colshape->set_name("shape");
- col->add_child(colshape);
- colshape->set_owner(p_node->get_owner());
- sb->set_owner(p_node->get_owner());
+ CollisionShape *cshape = memnew(CollisionShape);
+ cshape->set_shape(E->get());
+ col->add_child(cshape);
+
+ cshape->set_name("shape" + itos(idx));
+ cshape->set_owner(p_node->get_owner());
+
+ idx++;
+ }
+ }
+ }
} else if (_teststr(name, "navmesh") && Object::cast_to<MeshInstance>(p_node)) {
@@ -574,48 +620,35 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array
Ref<ArrayMesh> mesh = mi->get_mesh();
if (!mesh.is_null()) {
- if (_teststr(mesh->get_name(), "col") || _teststr(mesh->get_name(), "convcol")) {
- Ref<Shape> shape;
- if (_teststr(mesh->get_name(), "col")) {
- mesh->set_name(_fixstr(mesh->get_name(), "col"));
-
- if (collision_map.has(mesh)) {
- shape = collision_map[mesh];
-
- } else {
-
- shape = mesh->create_trimesh_shape();
- if (!shape.is_null())
- collision_map[mesh] = shape;
- }
- } else if (_teststr(mesh->get_name(), "convcol")) {
- mesh->set_name(_fixstr(mesh->get_name(), "convcol"));
+ List<Ref<Shape> > shapes;
+ if (collision_map.has(mesh)) {
+ shapes = collision_map[mesh];
+ } else if (_teststr(mesh->get_name(), "col")) {
+ _gen_shape_list(mesh, shapes, false);
+ collision_map[mesh] = shapes;
+ mesh->set_name(_fixstr(mesh->get_name(), "col"));
+ } else if (_teststr(mesh->get_name(), "convcol")) {
+ _gen_shape_list(mesh, shapes, true);
+ collision_map[mesh] = shapes;
+ mesh->set_name(_fixstr(mesh->get_name(), "convcol"));
+ }
- if (collision_map.has(mesh)) {
- shape = collision_map[mesh];
+ if (shapes.size()) {
+ StaticBody *col = memnew(StaticBody);
+ col->set_name("static_collision");
+ p_node->add_child(col);
+ col->set_owner(p_node->get_owner());
- } else {
+ int idx = 0;
+ for (List<Ref<Shape> >::Element *E = shapes.front(); E; E = E->next()) {
- shape = mesh->create_convex_shape();
- if (!shape.is_null())
- collision_map[mesh] = shape;
- }
- }
-
- if (!shape.is_null()) {
- StaticBody *col = memnew(StaticBody);
CollisionShape *cshape = memnew(CollisionShape);
- cshape->set_shape(shape);
+ cshape->set_shape(E->get());
col->add_child(cshape);
- col->set_transform(mi->get_transform());
- col->set_name(mi->get_name());
- p_node->replace_by(col);
- memdelete(p_node);
- p_node = col;
-
- cshape->set_name("shape");
+ cshape->set_name("shape" + itos(idx));
cshape->set_owner(p_node->get_owner());
+ idx++;
}
}
}
@@ -1269,7 +1302,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
float anim_optimizer_maxang = p_options["animation/optimizer/max_angle"];
int light_bake_mode = p_options["meshes/light_baking"];
- Map<Ref<ArrayMesh>, Ref<Shape> > collision_map;
+ Map<Ref<Mesh>, List<Ref<Shape> > > collision_map;
scene = _fix_node(scene, scene, collision_map, LightBakeMode(light_bake_mode));
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index 99f8b1a8e0..b10c4da2e5 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -146,7 +146,7 @@ public:
void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_keep_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes);
- Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<ArrayMesh>, Ref<Shape> > &collision_map, LightBakeMode p_light_bake_mode);
+ Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape> > > &collision_map, LightBakeMode p_light_bake_mode);
void _create_clips(Node *scene, const Array &p_clips, bool p_bake_all);
void _filter_anim_tracks(Ref<Animation> anim, Set<String> &keep);
diff --git a/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp
index 3e10cdbbfa..cf111dc4ce 100644
--- a/editor/plugins/mesh_instance_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_editor_plugin.cpp
@@ -95,10 +95,7 @@ void MeshInstanceEditor::_menu_option(int p_option) {
return;
}
- if (trimesh_shape)
- ur->create_action(TTR("Create Static Trimesh Body"));
- else
- ur->create_action(TTR("Create Static Convex Body"));
+ ur->create_action(TTR("Create Static Trimesh Body"));
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
@@ -132,8 +129,7 @@ void MeshInstanceEditor::_menu_option(int p_option) {
} break;
- case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE:
- case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: {
+ case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: {
if (node == get_tree()->get_edited_scene_root()) {
err_dialog->set_text(TTR("This doesn't work on scene root!"));
@@ -141,9 +137,7 @@ void MeshInstanceEditor::_menu_option(int p_option) {
return;
}
- bool trimesh_shape = (p_option == MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
-
- Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape();
+ Ref<Shape> shape = mesh->create_trimesh_shape();
if (shape.is_null())
return;
@@ -154,10 +148,7 @@ void MeshInstanceEditor::_menu_option(int p_option) {
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- if (trimesh_shape)
- ur->create_action(TTR("Create Trimesh Shape"));
- else
- ur->create_action(TTR("Create Convex Shape"));
+ ur->create_action(TTR("Create Trimesh Static Shape"));
ur->add_do_method(node->get_parent(), "add_child", cshape);
ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1);
@@ -165,6 +156,40 @@ void MeshInstanceEditor::_menu_option(int p_option) {
ur->add_do_reference(cshape);
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
ur->commit_action();
+ } break;
+ case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: {
+
+ if (node == get_tree()->get_edited_scene_root()) {
+ err_dialog->set_text(TTR("This doesn't work on scene root!"));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ Vector<Ref<Shape> > shapes = mesh->convex_decompose();
+
+ if (!shapes.size()) {
+ err_dialog->set_text(TTR("Failed creating shapes!"));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action(TTR("Create Convex Shape(s)"));
+
+ for (int i = 0; i < shapes.size(); i++) {
+
+ CollisionShape *cshape = memnew(CollisionShape);
+ cshape->set_shape(shapes[i]);
+
+ Node *owner = node->get_owner();
+
+ ur->add_do_method(node->get_parent(), "add_child", cshape);
+ ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1);
+ ur->add_do_method(cshape, "set_owner", owner);
+ ur->add_do_reference(cshape);
+ ur->add_undo_method(node->get_parent(), "remove_child", cshape);
+ }
+ ur->commit_action();
} break;
@@ -393,10 +418,9 @@ MeshInstanceEditor::MeshInstanceEditor() {
options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MeshInstance", "EditorIcons"));
options->get_popup()->add_item(TTR("Create Trimesh Static Body"), MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
- options->get_popup()->add_item(TTR("Create Convex Static Body"), MENU_OPTION_CREATE_STATIC_CONVEX_BODY);
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Create Trimesh Collision Sibling"), MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
- options->get_popup()->add_item(TTR("Create Convex Collision Sibling"), MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE);
+ options->get_popup()->add_item(TTR("Create Convex Collision Sibling(s)"), MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE);
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH);
options->get_popup()->add_separator();