Created
October 10, 2025 10:33
-
-
Save HungryProton/4d33370d5cea40d73656fd1bccc7444a to your computer and use it in GitHub Desktop.
Import script example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@tool | |
extends EditorScenePostImport | |
## Import script to automate various parts of the pipeline. Features: | |
## + Primitive collision shapes support | |
## + Shadow only meshes | |
## | |
## COLLISIONS: | |
## + Append '-static' to the node name to mark it as a static body | |
## + Add child empties to create the collision shapes | |
## - Supported shapes: -collider_box, -collider_sphere, -collider_cylinder | |
## | |
## SHADOW ONLY MESHES | |
## + Append '-shadow_only' to the mesh name to only cast shadows | |
func _post_import(scene: Node) -> Node: | |
print(scene.name) | |
scene = _process_colliders(scene) | |
_process_shadow_meshes(scene) | |
_fix_owner(scene, scene) | |
return scene | |
const COLLISION_STATIC := &"static" | |
const COLLISION_ANIMATABLE := &"animatable" | |
const COLLISION_KINEMATIC := &"kinematic" | |
const COLLISION_RIGID := &"rigid" | |
const COLLIDER_ROOT := &"-collider_" | |
const COLLIDER_BOX := &"_box" | |
const COLLIDER_SPHERE := &"_sphere" | |
const COLLIDER_CYLINDER := &"_cylinder" | |
const COLLISIONS := [COLLISION_STATIC, COLLISION_ANIMATABLE, COLLISION_KINEMATIC, COLLISION_RIGID] | |
func _process_colliders(root: Node) -> Node: | |
if root is Node3D: | |
root = _process_colliders_for_node(root as Node3D) | |
for child in root.get_children(): | |
@warning_ignore("return_value_discarded") | |
_process_colliders(child) | |
return root | |
# TODO: Add support for animatable and character body | |
func _process_colliders_for_node(node: Node3D) -> Node3D: | |
var splits := node.name.split("-") | |
var type: String = splits[-1] | |
if not type in COLLISIONS: | |
return node | |
node.name = node.name.trim_suffix("-" + type) | |
var body: PhysicsBody3D | |
match type: | |
COLLISION_STATIC: | |
body = StaticBody3D.new() | |
COLLISION_ANIMATABLE: | |
body = AnimatableBody3D.new() | |
COLLISION_KINEMATIC: | |
body = CharacterBody3D.new() | |
COLLISION_RIGID: | |
body = RigidBody3D.new() | |
body.name = node.name + "Collider" | |
body.scale = Vector3.ONE | |
for child: Node in node.get_children(): | |
if not child is Node3D: | |
continue | |
var ref: Node3D = child as Node3D | |
var shape := CollisionShape3D.new() | |
shape.transform = ref.transform | |
shape.scale = Vector3.ONE | |
if ref.name.ends_with(COLLIDER_BOX): | |
var box_shape := BoxShape3D.new() | |
box_shape.size = ref.scale * 2.0 | |
shape.shape = box_shape | |
elif ref.name.ends_with(COLLIDER_SPHERE): | |
var sphere_shape := SphereShape3D.new() | |
# TODO: Check is the scale is the same on all 3 axis | |
sphere_shape.radius = (ref.scale.x + ref.scale.y + ref.scale.z) / 3.0 # HACK | |
shape.shape = sphere_shape | |
elif ref.name.ends_with(COLLIDER_CYLINDER): | |
var cylinder_shape := CylinderShape3D.new() | |
cylinder_shape.height = ref.scale.y | |
cylinder_shape.radius = (ref.scale.x + ref.scale.y) / 4.0 # HACK | |
if shape.shape: | |
# Rename the collision shape and reparent the child nodes if any | |
var strip_from: int = ref.name.rfind(&"-") | |
shape.name = ref.name.left(strip_from) | |
body.add_child(shape, true) | |
for ref_child: Node in ref.get_children(): | |
ref_child.reparent(shape) | |
ref.queue_free() | |
else: | |
shape.queue_free() | |
if body.get_child_count() > 0: | |
node.add_child(body, true) | |
else: | |
body.queue_free() # No collision shape references found. | |
return node | |
const SHADOW_MESH := &"-shadows_only" | |
func _process_shadow_meshes(root: Node) -> void: | |
if root is GeometryInstance3D and root.name.ends_with(SHADOW_MESH): | |
(root as GeometryInstance3D).cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_SHADOWS_ONLY | |
root.name = root.name.trim_suffix(SHADOW_MESH) | |
for child in root.get_children(): | |
_process_shadow_meshes(child) | |
func _fix_owner(root: Node, owner: Node) -> void: | |
root.owner = owner | |
for child: Node in root.get_children(): | |
_fix_owner(child, owner) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment