Rework MeshInstance3d collision shape creation into a subMenu and add all static body options
Apply suggestions from code review Co-Authored-By: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com>
This commit is contained in:
parent
a4fbe4c01f
commit
b84f66c5df
2 changed files with 203 additions and 202 deletions
|
@ -59,6 +59,148 @@ void MeshInstance3DEditor::edit(MeshInstance3D *p_mesh) {
|
||||||
node = p_mesh;
|
node = p_mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<Ref<Shape3D>> MeshInstance3DEditor::create_shape_from_mesh(Ref<Mesh> p_mesh, int p_option, bool p_verbose) {
|
||||||
|
Vector<Ref<Shape3D>> shapes;
|
||||||
|
switch (p_option) {
|
||||||
|
case SHAPE_TYPE_TRIMESH: {
|
||||||
|
shapes.push_back(p_mesh->create_trimesh_shape());
|
||||||
|
|
||||||
|
if (p_verbose && shapes.is_empty()) {
|
||||||
|
err_dialog->set_text(TTR("Couldn't create a Trimesh collision shape."));
|
||||||
|
err_dialog->popup_centered();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case SHAPE_TYPE_SINGLE_CONVEX: {
|
||||||
|
shapes.push_back(p_mesh->create_convex_shape(true, false));
|
||||||
|
|
||||||
|
if (p_verbose && shapes.is_empty()) {
|
||||||
|
err_dialog->set_text(TTR("Couldn't create a single collision shape."));
|
||||||
|
err_dialog->popup_centered();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case SHAPE_TYPE_SIMPLIFIED_CONVEX: {
|
||||||
|
shapes.push_back(p_mesh->create_convex_shape(true, true));
|
||||||
|
|
||||||
|
if (p_verbose && shapes.is_empty()) {
|
||||||
|
err_dialog->set_text(TTR("Couldn't create a simplified collision shape."));
|
||||||
|
err_dialog->popup_centered();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case SHAPE_TYPE_MULTIPLE_CONVEX: {
|
||||||
|
Ref<MeshConvexDecompositionSettings> settings;
|
||||||
|
settings.instantiate();
|
||||||
|
settings->set_max_convex_hulls(32);
|
||||||
|
settings->set_max_concavity(0.001);
|
||||||
|
|
||||||
|
shapes = p_mesh->convex_decompose(settings);
|
||||||
|
|
||||||
|
if (p_verbose && shapes.is_empty()) {
|
||||||
|
err_dialog->set_text(TTR("Couldn't create any collision shapes."));
|
||||||
|
err_dialog->popup_centered();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return shapes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshInstance3DEditor::_create_collision_shape() {
|
||||||
|
int placement_option = shape_placement->get_selected();
|
||||||
|
int shape_type_option = shape_type->get_selected();
|
||||||
|
|
||||||
|
EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection();
|
||||||
|
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
|
||||||
|
|
||||||
|
switch (shape_type_option) {
|
||||||
|
case SHAPE_TYPE_TRIMESH: {
|
||||||
|
ur->create_action(TTR(placement_option == SHAPE_PLACEMENT_SIBLING ? "Create Trimesh Collision Shape Sibling" : "Create Trimesh Static Body"));
|
||||||
|
} break;
|
||||||
|
case SHAPE_TYPE_SINGLE_CONVEX: {
|
||||||
|
ur->create_action(TTR(placement_option == SHAPE_PLACEMENT_SIBLING ? "Create Single Convex Collision Shape Sibling" : "Create Single Convex Static Body"));
|
||||||
|
} break;
|
||||||
|
case SHAPE_TYPE_SIMPLIFIED_CONVEX: {
|
||||||
|
ur->create_action(TTR(placement_option == SHAPE_PLACEMENT_SIBLING ? "Create Simplified Convex Collision Shape Sibling" : "Create Simplified Convex Static Body"));
|
||||||
|
} break;
|
||||||
|
case SHAPE_TYPE_MULTIPLE_CONVEX: {
|
||||||
|
ur->create_action(TTR(placement_option == SHAPE_PLACEMENT_SIBLING ? "Create Multiple Convex Collision Shape Siblings" : "Create Multiple Convex Static Body"));
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Node *> selection = editor_selection->get_selected_node_list();
|
||||||
|
|
||||||
|
bool verbose = false;
|
||||||
|
if (selection.is_empty()) {
|
||||||
|
selection.push_back(node);
|
||||||
|
verbose = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Node *E : selection) {
|
||||||
|
if (placement_option == SHAPE_PLACEMENT_SIBLING && E == get_tree()->get_edited_scene_root()) {
|
||||||
|
if (verbose) {
|
||||||
|
err_dialog->set_text(TTR("Can't create a collision shape as sibling for the scene root."));
|
||||||
|
err_dialog->popup_centered();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshInstance3D *instance = Object::cast_to<MeshInstance3D>(E);
|
||||||
|
if (!instance) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Mesh> m = instance->get_mesh();
|
||||||
|
if (m.is_null()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<Ref<Shape3D>> shapes = create_shape_from_mesh(m, shape_type_option, verbose);
|
||||||
|
if (shapes.is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *owner = get_tree()->get_edited_scene_root();
|
||||||
|
if (placement_option == SHAPE_PLACEMENT_STATIC_BODY_CHILD) {
|
||||||
|
StaticBody3D *body = memnew(StaticBody3D);
|
||||||
|
|
||||||
|
ur->add_do_method(instance, "add_child", body, true);
|
||||||
|
ur->add_do_method(body, "set_owner", owner);
|
||||||
|
ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, body);
|
||||||
|
|
||||||
|
for (Ref<Shape3D> shape : shapes) {
|
||||||
|
CollisionShape3D *cshape = memnew(CollisionShape3D);
|
||||||
|
cshape->set_shape(shape);
|
||||||
|
body->add_child(cshape, true);
|
||||||
|
ur->add_do_method(cshape, "set_owner", owner);
|
||||||
|
ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
|
||||||
|
}
|
||||||
|
ur->add_do_reference(body);
|
||||||
|
ur->add_undo_method(instance, "remove_child", body);
|
||||||
|
} else {
|
||||||
|
for (Ref<Shape3D> shape : shapes) {
|
||||||
|
CollisionShape3D *cshape = memnew(CollisionShape3D);
|
||||||
|
cshape->set_shape(shape);
|
||||||
|
cshape->set_name("CollisionShape3D");
|
||||||
|
cshape->set_transform(node->get_transform());
|
||||||
|
ur->add_do_method(E->get_parent(), "add_child", cshape);
|
||||||
|
ur->add_do_method(E->get_parent(), "move_child", cshape, E->get_index() + 1);
|
||||||
|
ur->add_do_method(cshape, "set_owner", owner);
|
||||||
|
ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
|
||||||
|
ur->add_do_reference(cshape);
|
||||||
|
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ur->commit_action();
|
||||||
|
}
|
||||||
|
|
||||||
void MeshInstance3DEditor::_menu_option(int p_option) {
|
void MeshInstance3DEditor::_menu_option(int p_option) {
|
||||||
Ref<Mesh> mesh = node->get_mesh();
|
Ref<Mesh> mesh = node->get_mesh();
|
||||||
if (mesh.is_null()) {
|
if (mesh.is_null()) {
|
||||||
|
@ -68,191 +210,8 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (p_option) {
|
switch (p_option) {
|
||||||
case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: {
|
case MENU_OPTION_CREATE_COLLISION_SHAPE: {
|
||||||
EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection();
|
shape_dialog->popup_centered();
|
||||||
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
|
|
||||||
|
|
||||||
List<Node *> selection = editor_selection->get_selected_node_list();
|
|
||||||
|
|
||||||
if (selection.is_empty()) {
|
|
||||||
Ref<ConcavePolygonShape3D> shape = mesh->create_trimesh_shape();
|
|
||||||
if (shape.is_null()) {
|
|
||||||
err_dialog->set_text(TTR("Couldn't create a Trimesh collision shape."));
|
|
||||||
err_dialog->popup_centered();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CollisionShape3D *cshape = memnew(CollisionShape3D);
|
|
||||||
cshape->set_shape(shape);
|
|
||||||
StaticBody3D *body = memnew(StaticBody3D);
|
|
||||||
body->add_child(cshape, true);
|
|
||||||
|
|
||||||
Node *owner = get_tree()->get_edited_scene_root();
|
|
||||||
|
|
||||||
ur->create_action(TTR("Create Static Trimesh Body"));
|
|
||||||
ur->add_do_method(node, "add_child", body, true);
|
|
||||||
ur->add_do_method(body, "set_owner", owner);
|
|
||||||
ur->add_do_method(cshape, "set_owner", owner);
|
|
||||||
ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, body);
|
|
||||||
ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
|
|
||||||
ur->add_do_reference(body);
|
|
||||||
ur->add_undo_method(node, "remove_child", body);
|
|
||||||
ur->commit_action();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ur->create_action(TTR("Create Static Trimesh Body"));
|
|
||||||
|
|
||||||
for (Node *E : selection) {
|
|
||||||
MeshInstance3D *instance = Object::cast_to<MeshInstance3D>(E);
|
|
||||||
if (!instance) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<Mesh> m = instance->get_mesh();
|
|
||||||
if (m.is_null()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<ConcavePolygonShape3D> shape = m->create_trimesh_shape();
|
|
||||||
if (shape.is_null()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CollisionShape3D *cshape = memnew(CollisionShape3D);
|
|
||||||
cshape->set_shape(shape);
|
|
||||||
StaticBody3D *body = memnew(StaticBody3D);
|
|
||||||
body->add_child(cshape, true);
|
|
||||||
|
|
||||||
Node *owner = get_tree()->get_edited_scene_root();
|
|
||||||
|
|
||||||
ur->add_do_method(instance, "add_child", body, true);
|
|
||||||
ur->add_do_method(body, "set_owner", owner);
|
|
||||||
ur->add_do_method(cshape, "set_owner", owner);
|
|
||||||
ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, body);
|
|
||||||
ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
|
|
||||||
ur->add_do_reference(body);
|
|
||||||
ur->add_undo_method(instance, "remove_child", body);
|
|
||||||
}
|
|
||||||
|
|
||||||
ur->commit_action();
|
|
||||||
|
|
||||||
} break;
|
|
||||||
|
|
||||||
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!"));
|
|
||||||
err_dialog->popup_centered();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<ConcavePolygonShape3D> shape = mesh->create_trimesh_shape();
|
|
||||||
if (shape.is_null()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CollisionShape3D *cshape = memnew(CollisionShape3D);
|
|
||||||
cshape->set_shape(shape);
|
|
||||||
cshape->set_transform(node->get_transform());
|
|
||||||
|
|
||||||
Node *owner = get_tree()->get_edited_scene_root();
|
|
||||||
|
|
||||||
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
|
|
||||||
|
|
||||||
ur->create_action(TTR("Create Trimesh Static Shape"));
|
|
||||||
|
|
||||||
ur->add_do_method(node->get_parent(), "add_child", cshape, true);
|
|
||||||
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_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
|
|
||||||
ur->add_do_reference(cshape);
|
|
||||||
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
|
|
||||||
ur->commit_action();
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE:
|
|
||||||
case MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE: {
|
|
||||||
if (node == get_tree()->get_edited_scene_root()) {
|
|
||||||
err_dialog->set_text(TTR("Can't create a single convex collision shape for the scene root."));
|
|
||||||
err_dialog->popup_centered();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool simplify = (p_option == MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE);
|
|
||||||
|
|
||||||
Ref<ConvexPolygonShape3D> shape = mesh->create_convex_shape(true, simplify);
|
|
||||||
|
|
||||||
if (shape.is_null()) {
|
|
||||||
err_dialog->set_text(TTR("Couldn't create a single convex collision shape."));
|
|
||||||
err_dialog->popup_centered();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
|
|
||||||
|
|
||||||
if (simplify) {
|
|
||||||
ur->create_action(TTR("Create Simplified Convex Shape"));
|
|
||||||
} else {
|
|
||||||
ur->create_action(TTR("Create Single Convex Shape"));
|
|
||||||
}
|
|
||||||
|
|
||||||
CollisionShape3D *cshape = memnew(CollisionShape3D);
|
|
||||||
cshape->set_shape(shape);
|
|
||||||
cshape->set_transform(node->get_transform());
|
|
||||||
|
|
||||||
Node *owner = get_tree()->get_edited_scene_root();
|
|
||||||
|
|
||||||
ur->add_do_method(node->get_parent(), "add_child", cshape, true);
|
|
||||||
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_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
|
|
||||||
ur->add_do_reference(cshape);
|
|
||||||
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
|
|
||||||
|
|
||||||
ur->commit_action();
|
|
||||||
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES: {
|
|
||||||
if (node == get_tree()->get_edited_scene_root()) {
|
|
||||||
err_dialog->set_text(TTR("Can't create multiple convex collision shapes for the scene root."));
|
|
||||||
err_dialog->popup_centered();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<MeshConvexDecompositionSettings> settings = Ref<MeshConvexDecompositionSettings>();
|
|
||||||
settings.instantiate();
|
|
||||||
settings->set_max_convex_hulls(32);
|
|
||||||
settings->set_max_concavity(0.001);
|
|
||||||
|
|
||||||
Vector<Ref<Shape3D>> shapes = mesh->convex_decompose(settings);
|
|
||||||
|
|
||||||
if (!shapes.size()) {
|
|
||||||
err_dialog->set_text(TTR("Couldn't create any collision shapes."));
|
|
||||||
err_dialog->popup_centered();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
|
|
||||||
|
|
||||||
ur->create_action(TTR("Create Multiple Convex Shapes"));
|
|
||||||
|
|
||||||
for (int i = 0; i < shapes.size(); i++) {
|
|
||||||
CollisionShape3D *cshape = memnew(CollisionShape3D);
|
|
||||||
cshape->set_name("CollisionShape3D");
|
|
||||||
|
|
||||||
cshape->set_shape(shapes[i]);
|
|
||||||
cshape->set_transform(node->get_transform());
|
|
||||||
|
|
||||||
Node *owner = get_tree()->get_edited_scene_root();
|
|
||||||
|
|
||||||
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_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
|
|
||||||
ur->add_do_reference(cshape);
|
|
||||||
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
|
|
||||||
}
|
|
||||||
ur->commit_action();
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MENU_OPTION_CREATE_NAVMESH: {
|
case MENU_OPTION_CREATE_NAVMESH: {
|
||||||
|
@ -571,18 +530,7 @@ MeshInstance3DEditor::MeshInstance3DEditor() {
|
||||||
options->set_switch_on_hover(true);
|
options->set_switch_on_hover(true);
|
||||||
Node3DEditor::get_singleton()->add_control_to_menu_panel(options);
|
Node3DEditor::get_singleton()->add_control_to_menu_panel(options);
|
||||||
|
|
||||||
options->get_popup()->add_item(TTR("Create Trimesh Static Body"), MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
|
options->get_popup()->add_item(TTR("Create Collision Shape..."), MENU_OPTION_CREATE_COLLISION_SHAPE);
|
||||||
options->get_popup()->set_item_tooltip(-1, TTR("Creates a StaticBody3D and assigns a polygon-based collision shape to it automatically.\nThis is the most accurate (but slowest) option for collision detection."));
|
|
||||||
options->get_popup()->add_separator();
|
|
||||||
options->get_popup()->add_item(TTR("Create Trimesh Collision Sibling"), MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
|
|
||||||
options->get_popup()->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection."));
|
|
||||||
options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE);
|
|
||||||
options->get_popup()->set_item_tooltip(-1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection."));
|
|
||||||
options->get_popup()->add_item(TTR("Create Simplified Convex Collision Sibling"), MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE);
|
|
||||||
options->get_popup()->set_item_tooltip(-1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy."));
|
|
||||||
options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES);
|
|
||||||
options->get_popup()->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision."));
|
|
||||||
options->get_popup()->add_separator();
|
|
||||||
options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH);
|
options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH);
|
||||||
options->get_popup()->add_separator();
|
options->get_popup()->add_separator();
|
||||||
options->get_popup()->add_item(TTR("Create Outline Mesh..."), MENU_OPTION_CREATE_OUTLINE_MESH);
|
options->get_popup()->add_item(TTR("Create Outline Mesh..."), MENU_OPTION_CREATE_OUTLINE_MESH);
|
||||||
|
@ -613,6 +561,44 @@ MeshInstance3DEditor::MeshInstance3DEditor() {
|
||||||
add_child(outline_dialog);
|
add_child(outline_dialog);
|
||||||
outline_dialog->connect("confirmed", callable_mp(this, &MeshInstance3DEditor::_create_outline_mesh));
|
outline_dialog->connect("confirmed", callable_mp(this, &MeshInstance3DEditor::_create_outline_mesh));
|
||||||
|
|
||||||
|
shape_dialog = memnew(ConfirmationDialog);
|
||||||
|
shape_dialog->set_title(TTR("Create Collision Shape"));
|
||||||
|
shape_dialog->set_ok_button_text(TTR("Create"));
|
||||||
|
|
||||||
|
VBoxContainer *shape_dialog_vbc = memnew(VBoxContainer);
|
||||||
|
shape_dialog->add_child(shape_dialog_vbc);
|
||||||
|
|
||||||
|
Label *l = memnew(Label);
|
||||||
|
l->set_text(TTR("Collision Shape placement"));
|
||||||
|
shape_dialog_vbc->add_child(l);
|
||||||
|
|
||||||
|
shape_placement = memnew(OptionButton);
|
||||||
|
shape_placement->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
shape_placement->add_item(TTR("Sibling"), SHAPE_PLACEMENT_SIBLING);
|
||||||
|
shape_placement->set_item_tooltip(-1, TTR("Creates collision shapes as Sibling."));
|
||||||
|
shape_placement->add_item(TTR("Static Body Child"), SHAPE_PLACEMENT_STATIC_BODY_CHILD);
|
||||||
|
shape_placement->set_item_tooltip(-1, TTR("Creates a StaticBody3D as child and assigns collision shapes to it."));
|
||||||
|
shape_dialog_vbc->add_child(shape_placement);
|
||||||
|
|
||||||
|
l = memnew(Label);
|
||||||
|
l->set_text(TTR("Collision Shape Type"));
|
||||||
|
shape_dialog_vbc->add_child(l);
|
||||||
|
|
||||||
|
shape_type = memnew(OptionButton);
|
||||||
|
shape_type->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
shape_type->add_item(TTR("Trimesh"), SHAPE_TYPE_TRIMESH);
|
||||||
|
shape_type->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection."));
|
||||||
|
shape_type->add_item(TTR("Single Convex"), SHAPE_TYPE_SINGLE_CONVEX);
|
||||||
|
shape_type->set_item_tooltip(-1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection."));
|
||||||
|
shape_type->add_item(TTR("Simplified Convex"), SHAPE_TYPE_SIMPLIFIED_CONVEX);
|
||||||
|
shape_type->set_item_tooltip(-1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy."));
|
||||||
|
shape_type->add_item(TTR("Multiple Convex"), SHAPE_TYPE_MULTIPLE_CONVEX);
|
||||||
|
shape_type->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision."));
|
||||||
|
shape_dialog_vbc->add_child(shape_type);
|
||||||
|
|
||||||
|
add_child(shape_dialog);
|
||||||
|
shape_dialog->connect("confirmed", callable_mp(this, &MeshInstance3DEditor::_create_collision_shape));
|
||||||
|
|
||||||
err_dialog = memnew(AcceptDialog);
|
err_dialog = memnew(AcceptDialog);
|
||||||
add_child(err_dialog);
|
add_child(err_dialog);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include "editor/editor_plugin.h"
|
#include "editor/editor_plugin.h"
|
||||||
#include "scene/3d/mesh_instance_3d.h"
|
#include "scene/3d/mesh_instance_3d.h"
|
||||||
|
#include "scene/gui/option_button.h"
|
||||||
|
|
||||||
class AcceptDialog;
|
class AcceptDialog;
|
||||||
class ConfirmationDialog;
|
class ConfirmationDialog;
|
||||||
|
@ -43,11 +44,7 @@ class MeshInstance3DEditor : public Control {
|
||||||
GDCLASS(MeshInstance3DEditor, Control);
|
GDCLASS(MeshInstance3DEditor, Control);
|
||||||
|
|
||||||
enum Menu {
|
enum Menu {
|
||||||
MENU_OPTION_CREATE_STATIC_TRIMESH_BODY,
|
MENU_OPTION_CREATE_COLLISION_SHAPE,
|
||||||
MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE,
|
|
||||||
MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE,
|
|
||||||
MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE,
|
|
||||||
MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES,
|
|
||||||
MENU_OPTION_CREATE_NAVMESH,
|
MENU_OPTION_CREATE_NAVMESH,
|
||||||
MENU_OPTION_CREATE_OUTLINE_MESH,
|
MENU_OPTION_CREATE_OUTLINE_MESH,
|
||||||
MENU_OPTION_CREATE_DEBUG_TANGENTS,
|
MENU_OPTION_CREATE_DEBUG_TANGENTS,
|
||||||
|
@ -56,6 +53,18 @@ class MeshInstance3DEditor : public Control {
|
||||||
MENU_OPTION_DEBUG_UV2,
|
MENU_OPTION_DEBUG_UV2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ShapePlacement {
|
||||||
|
SHAPE_PLACEMENT_SIBLING,
|
||||||
|
SHAPE_PLACEMENT_STATIC_BODY_CHILD,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ShapeType {
|
||||||
|
SHAPE_TYPE_TRIMESH,
|
||||||
|
SHAPE_TYPE_SINGLE_CONVEX,
|
||||||
|
SHAPE_TYPE_SIMPLIFIED_CONVEX,
|
||||||
|
SHAPE_TYPE_MULTIPLE_CONVEX,
|
||||||
|
};
|
||||||
|
|
||||||
MeshInstance3D *node = nullptr;
|
MeshInstance3D *node = nullptr;
|
||||||
|
|
||||||
MenuButton *options = nullptr;
|
MenuButton *options = nullptr;
|
||||||
|
@ -63,12 +72,18 @@ class MeshInstance3DEditor : public Control {
|
||||||
ConfirmationDialog *outline_dialog = nullptr;
|
ConfirmationDialog *outline_dialog = nullptr;
|
||||||
SpinBox *outline_size = nullptr;
|
SpinBox *outline_size = nullptr;
|
||||||
|
|
||||||
|
ConfirmationDialog *shape_dialog = nullptr;
|
||||||
|
OptionButton *shape_type = nullptr;
|
||||||
|
OptionButton *shape_placement = nullptr;
|
||||||
|
|
||||||
AcceptDialog *err_dialog = nullptr;
|
AcceptDialog *err_dialog = nullptr;
|
||||||
|
|
||||||
AcceptDialog *debug_uv_dialog = nullptr;
|
AcceptDialog *debug_uv_dialog = nullptr;
|
||||||
Control *debug_uv = nullptr;
|
Control *debug_uv = nullptr;
|
||||||
Vector<Vector2> uv_lines;
|
Vector<Vector2> uv_lines;
|
||||||
|
|
||||||
|
void _create_collision_shape();
|
||||||
|
Vector<Ref<Shape3D>> create_shape_from_mesh(Ref<Mesh> p_mesh, int p_option, bool p_verbose);
|
||||||
void _menu_option(int p_option);
|
void _menu_option(int p_option);
|
||||||
void _create_outline_mesh();
|
void _create_outline_mesh();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue