monkeystudio / tests /self_test.gd
geter62's picture
Upload folder using huggingface_hub
84e8204 verified
Raw History Blame Contribute Delete
5.51 kB
extends Node
##
## SelfTest - headless verification of every core subsystem.
## Run: godot --headless res://tests/self_test.tscn
##
## Exits with code 0 if all checks pass, 1 otherwise. This is the regression
## gate for the modules; it does not need a display or GPU.
##
var _failures := 0
var _host: Node3D
func _ready() -> void:
_host = Node3D.new()
_host.name = "TestHost"
var geom := Node3D.new()
geom.name = "Geometry"
_host.add_child(geom)
var rig := Node3D.new()
rig.name = "Rig"
_host.add_child(rig)
add_child(_host)
_test_memory_manager()
_test_mesh_generators()
_test_sculpt()
_test_rigging()
_test_simulation()
_test_timeline()
print("")
if _failures == 0:
print("SELFTEST: ALL PASS")
get_tree().quit(0)
else:
print("SELFTEST: %d FAILURE(S)" % _failures)
get_tree().quit(1)
func _check(name: String, cond: bool) -> void:
if cond:
print(" [PASS] ", name)
else:
_failures += 1
print(" [FAIL] ", name)
func _test_memory_manager() -> void:
print("[Test] MemoryManager")
_check("budget set", MemoryManager.asset_budget_mb > 0.0)
_check("feature count >= 20", FeatureRegistry.feature_count() >= 20)
var snap := MemoryManager.debug_snapshot()
_check("snapshot has budget", snap.has("budget_mb"))
func _load_module(path: String) -> Node:
var script: GDScript = load(path)
var n: Node = script.new()
_host.add_child(n)
if n.has_method("_activate"):
n.call("_activate", _host)
return n
func _test_mesh_generators() -> void:
print("[Test] Mesh generators")
var mg := _load_module("res://scripts/modules/mesh_gen.gd")
for kind in ["cube", "sphere", "cylinder", "plane", "torus", "ico", "suzanne"]:
var data: Dictionary = mg.call("generate", kind, {})
var vcount: int = (data["verts"] as PackedVector3Array).size()
var icount: int = (data["indices"] as PackedInt32Array).size()
_check("%s has verts & tris (v=%d,i=%d)" % [kind, vcount, icount], vcount > 0 and icount > 0)
var mi: MeshInstance3D = mg.call("spawn", "sphere", {"radius": 1.0})
_check("spawn returns MeshInstance3D", mi != null and mi.mesh != null and mi.mesh.get_surface_count() == 1)
var cost := VertexBufferManager.estimate_cost_mb(1000)
_check("cost estimate > 0", cost > 0.0)
mg.queue_free()
func _test_sculpt() -> void:
print("[Test] Sculpting")
var mg := _load_module("res://scripts/modules/mesh_gen.gd")
var sc := _load_module("res://scripts/modules/sculpt.gd")
var mi: MeshInstance3D = mg.call("spawn", "sphere", {"radius": 1.0})
sc.call("set_target", mi)
var before: PackedVector3Array = (mi.mesh.surface_get_arrays(0)[Mesh.ARRAY_VERTEX] as PackedVector3Array).duplicate()
for brush in ["draw", "grab", "pinch", "smooth", "flatten"]:
sc.set("_brush_id", brush)
sc.call("begin", Vector3(0, 1, 0))
sc.call("apply", Vector3(0, 1, 0), Vector3(0, 0.1, 0))
sc.call("apply", Vector3(0, 1, 0), Vector3(0.05, 0.1, 0))
sc.call("end")
var after: PackedVector3Array = mi.mesh.surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
var changed := false
for i in range(mini(before.size(), after.size())):
if before[i].distance_to(after[i]) > 0.0001:
changed = true
break
_check("sculpt modified vertices", changed)
_check("mesh still valid after sculpt", mi.mesh.get_surface_count() == 1)
mg.queue_free()
sc.queue_free()
func _test_rigging() -> void:
print("[Test] Rigging")
var mg := _load_module("res://scripts/modules/mesh_gen.gd")
var rg := _load_module("res://scripts/modules/rigging.gd")
var mi: MeshInstance3D = mg.call("spawn", "cube", {"size": 1.0})
rg.call("generate_default_armature", mi)
_check("bones created", int(rg.call("bone_count")) >= 9)
_check("mesh has skin", mi.skin != null)
_check("mesh has skeleton path", mi.skeleton != NodePath())
if mi.mesh.get_surface_count() > 0:
var arr: Array = mi.mesh.surface_get_arrays(0)
_check("bones channel present", arr[Mesh.ARRAY_BONES] != null)
_check("weights channel present", arr[Mesh.ARRAY_WEIGHTS] != null)
mg.queue_free()
rg.queue_free()
func _test_simulation() -> void:
print("[Test] Simulation")
var sim := _load_module("res://scripts/modules/simulation.gd")
sim.call("create_cloth", "sim.cloth", 6, 6, 1.0)
var before: PackedVector3Array = (sim.get("_sims")["sim.cloth"]["particles"] as PackedVector3Array).duplicate()
for i in range(30):
sim.call("_step", sim.get("_sims")["sim.cloth"])
sim.call("_upload", sim.get("_sims")["sim.cloth"])
var after: PackedVector3Array = sim.get("_sims")["sim.cloth"]["particles"]
var moved := false
for i in range(after.size()):
if before[i].distance_to(after[i]) > 0.0001:
moved = true
break
_check("cloth fell under gravity", moved)
var mesh: ArrayMesh = sim.get("_sims")["sim.cloth"]["mesh"]
_check("cloth mesh uploaded", mesh.get_surface_count() == 1)
sim.call("create_hair", "sim.hair", 4, 5)
_check("hair sim created", int(sim.call("active_sim_count")) >= 2)
sim.queue_free()
func _test_timeline() -> void:
print("[Test] Timeline")
var mg := _load_module("res://scripts/modules/mesh_gen.gd")
var tl := _load_module("res://scripts/modules/timeline.gd")
var mi: MeshInstance3D = mg.call("spawn", "cube", {"size": 1.0})
tl.call("add_keyframe", mi, "position", 0.0, Vector3.ZERO)
tl.call("add_keyframe", mi, "position", 1.0, Vector3(0, 2, 0))
_check("track created", int(tl.call("track_count")) >= 1)
_check("key count == 2", int(tl.call("key_count")) == 2)
tl.call("scrub", 0.5)
_check("scrub clamps/works", absf(float(tl.call("playhead")) - 0.5) < 0.001)
mg.queue_free()
tl.queue_free()