class_name CockpitMeshFactory extends RefCounted static func add_box( node_name: String, parent: Node3D, position: Vector3, size: Vector3, material: Material, rotation_degrees: Vector3 = Vector3.ZERO ) -> MeshInstance3D: var instance := MeshInstance3D.new() instance.name = node_name var mesh := BoxMesh.new() mesh.size = size instance.mesh = mesh instance.material_override = material instance.position = position instance.rotation_degrees = rotation_degrees parent.add_child(instance) return instance static func add_cylinder( node_name: String, parent: Node3D, position: Vector3, radius: float, height: float, material: Material, rotation_degrees: Vector3 = Vector3.ZERO ) -> MeshInstance3D: var instance := MeshInstance3D.new() instance.name = node_name var mesh := CylinderMesh.new() mesh.top_radius = radius mesh.bottom_radius = radius mesh.height = height mesh.radial_segments = 16 instance.mesh = mesh instance.material_override = material instance.position = position instance.rotation_degrees = rotation_degrees parent.add_child(instance) return instance static func add_cylinder_between( node_name: String, parent: Node3D, start: Vector3, end: Vector3, radius: float, material: Material ) -> MeshInstance3D: var direction := end - start var instance := add_cylinder( node_name, parent, (start + end) * 0.5, radius, direction.length(), material ) if not direction.is_zero_approx(): instance.quaternion = Quaternion(Vector3.UP, direction.normalized()) return instance static func add_sphere( node_name: String, parent: Node3D, position: Vector3, radius: float, material: Material ) -> MeshInstance3D: var instance := MeshInstance3D.new() instance.name = node_name var mesh := SphereMesh.new() mesh.radius = radius mesh.height = radius * 2.0 mesh.radial_segments = 16 mesh.rings = 8 instance.mesh = mesh instance.material_override = material instance.position = position parent.add_child(instance) return instance ## Gives an imported mesh instance its own copy of its first surface material, ## so driving a property (emission) never edits the resource shared by the model. static func own_surface_material(instance: MeshInstance3D) -> BaseMaterial3D: if instance == null or instance.mesh == null or instance.mesh.get_surface_count() == 0: return null var shared := instance.mesh.surface_get_material(0) as BaseMaterial3D if shared == null: return null var owned := shared.duplicate() as BaseMaterial3D instance.set_surface_override_material(0, owned) return owned ## Stops every mesh under `root` (root included) from casting shadows. static func disable_shadow_casting(root: Node) -> void: if root == null: return var meshes: Array[Node] = root.find_children("*", "MeshInstance3D", true, false) meshes.append(root) for node: Node in meshes: if node is MeshInstance3D: (node as MeshInstance3D).cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF