TowerGame/addons/PathMesh3D/scripts/path_mesh_3d_options.gd

146 lines
4.7 KiB
GDScript3
Raw Normal View History

2025-04-20 20:55:30 +01:00
@tool
extends MenuButton
enum Operation {BAKE, COLLISION}
enum Shape {TRIMESH, SINGLE_CONVEX, SIMPLE_CONVEX, MULTIPLE_CONVEX}
enum Placement {SIBLING, CHILD}
var path_mesh: Node
var ur: EditorUndoRedoManager
@onready var _err_dialog: AcceptDialog = $ErrDialog
@onready var _collision_dialog: ConfirmationDialog = $CollisionDialog
@onready var _shape_placement: OptionButton = $CollisionDialog/VBoxContainer/OptionButton
@onready var _shape_type: OptionButton = $CollisionDialog/VBoxContainer/OptionButton2
@onready var _bake_dialog: ConfirmationDialog = $BakeDialog
@onready var _bake_placement: OptionButton = $BakeDialog/VBoxContainer/OptionButton
func _ready() -> void:
get_popup().index_pressed.connect(_on_menu_pressed)
_bake_dialog.confirmed.connect(_on_bake_confirmed)
_collision_dialog.confirmed.connect(_on_collision_shape_confirmed)
func _on_menu_pressed(id: int) -> void:
match id:
Operation.BAKE:
_bake_dialog.popup_centered()
Operation.COLLISION:
_collision_dialog.popup_centered()
func _on_bake_confirmed() -> void:
if not (path_mesh is PathMesh3D or path_mesh is PathExtrude3D):
return
if not ur:
return
var placement := _bake_placement.selected
var p_owner := EditorInterface.get_edited_scene_root()
if p_owner == path_mesh and placement == Placement.SIBLING:
_err_dialog.dialog_text = "Can't add Mesh Instance as sibling of scene root."
_err_dialog.popup_centered()
return
var mesh: Mesh = path_mesh.get_baked_mesh()
if mesh == null:
_err_dialog.dialog_text = "No mesh to create Instance from."
_err_dialog.popup_centered()
return
var minstance := MeshInstance3D.new()
minstance.mesh = mesh
minstance.name = "MeshInstance3D"
if placement == Placement.SIBLING:
ur.add_do_method(path_mesh, "add_sibling", minstance, true)
ur.add_do_method(minstance, "set_owner", p_owner)
ur.add_do_reference(minstance)
ur.add_undo_method(path_mesh.get_parent(), "remove_child", minstance)
else:
ur.add_do_method(path_mesh, "add_child", minstance, true)
ur.add_do_method(minstance, "set_owner", p_owner)
ur.add_do_reference(minstance)
ur.add_undo_method(path_mesh, "remove_child", minstance)
ur.commit_action()
func _on_collision_shape_confirmed() -> void:
if not (path_mesh is PathMesh3D or path_mesh is PathExtrude3D):
return
if not ur:
return
var mesh: Mesh = path_mesh.get_baked_mesh()
if mesh == null:
_err_dialog.dialog_text = "No mesh to create Collision Shape from."
_err_dialog.popup_centered()
return
var placement := _shape_placement.selected
var shape_type := _shape_type.selected
var str := "Collision Shape Sibling" if placement == Placement.SIBLING else "Static Body"
match shape_type:
Shape.TRIMESH: ur.create_action("Create Trimesh " + str)
Shape.SINGLE_CONVEX: ur.create_action("Create Single Convex " + str)
Shape.SIMPLE_CONVEX: ur.create_action("Create Simplified Convex "+ str)
Shape.MULTIPLE_CONVEX: ur.create_action("Create Multiple Convex " + str)
_: return
if EditorInterface.get_edited_scene_root() == path_mesh and placement == 0:
_err_dialog.dialog_text = "Can't create a collision shape as sibling for the scene root."
_err_dialog.popup_centered()
return
var scene_owner := EditorInterface.get_edited_scene_root()
var shapes: Array[Shape3D] = []
match shape_type:
Shape.TRIMESH:
shapes.push_back(mesh.create_trimesh_shape())
Shape.SINGLE_CONVEX:
shapes.push_back(mesh.create_convex_shape(true, false))
Shape.SIMPLE_CONVEX:
shapes.push_back(mesh.create_convex_shape(true, true))
Shape.MULTIPLE_CONVEX:
var settings := MeshConvexDecompositionSettings.new()
settings.max_convex_hulls = 32
settings.max_concavity = 0.001
shapes = mesh.convex_decompose(settings)
if shapes.is_empty():
_err_dialog.dialog_text = "Cannot create collision shape."
_err_dialog.popup_centered()
return
var p_owner := EditorInterface.get_edited_scene_root()
if placement == Placement.CHILD:
var body := StaticBody3D.new()
ur.add_do_method(path_mesh, "add_child", body, true)
ur.add_do_method(body, "set_owner", p_owner)
for shape: Shape3D in shapes:
var cshape := CollisionShape3D.new()
cshape.shape = shape
ur.add_do_method(body, "add_child", cshape, true)
ur.add_do_method(cshape, "set_owner", p_owner)
ur.add_do_reference(body)
ur.add_undo_method(path_mesh, "remove_child", body)
else:
for shape: Shape3D in shapes:
var cshape := CollisionShape3D.new()
cshape.shape = shape
cshape.name = "CollisionShape3D"
cshape.transform = path_mesh.transform
ur.add_do_method(path_mesh, "add_sibling", cshape, true)
ur.add_do_method(cshape, "set_owner", p_owner)
ur.add_do_reference(cshape)
ur.add_undo_method(path_mesh.get_parent(), "remove_child", cshape)
ur.commit_action()