Download tests/self_test.gd from geter62/monkeystudio: direct link, hf CLI and curl.
- Browser
- Download file 5.51 kB
-
https://huggingface.co/geter62/monkeystudio/resolve/main/tests/self_test.gd
- Command line
-
hf download hf://geter62/monkeystudio/tests/self_test.gd
-
curl -L -o self_test.gd https://huggingface.co/geter62/monkeystudio/resolve/main/tests/self_test.gd
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() | |