Reorganize the codebase into role-based folders (snake_case)

Move the 40-odd root-level scripts and scenes into a tree that groups by role,
per the approved roadmap (WS2/WS3): actors/{player,matador,bear}, systems/{combat,
fx,input,debug,render,crowd,config}, ui/, props/ (was tscn_s/). Rename the shell
scene.tscn -> levels/game_shell.tscn and every PascalCase scene to snake_case
(Player.tscn -> player.tscn, MainMenu.tscn -> main_menu.tscn, etc.) so the
case-insensitive web/macOS filesystems can't alias two files together.

Done as a scripted move: each file travels with its .uid; every quoted res:// path
across scenes, scripts, .tres, and project.godot's 9 autoloads is rewritten; the
.godot uid/class cache is rebuilt from scratch. Scenes still resolve by uid, so the
rewrite is belt-and-suspenders. Lint globs (run_tests.sh + both CI workflows) now
walk the new dirs; an orphan animation_tree.gd.uid and 7 pre-existing trailing-
whitespace lints (barrel/torch, never covered by the old root-only glob) are cleaned.

Full suite green on both sides. Asset consolidation (Assets/Animations/fonts ->
art/) is deferred — moving imported .glb/.png/.ttf is safer done in the editor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017KoYBYQgRyY1zDHXMsXY3V
This commit is contained in:
2026-09-06 00:04:41 +03:00
parent b839252fe0
commit 7b6a141767
141 changed files with 199 additions and 158 deletions
+2 -2
View File
@@ -67,11 +67,11 @@ func _make_floor() -> StaticBody3D:
func _run() -> void:
root.add_child(_make_floor())
_bull = (load("res://Player.tscn") as PackedScene).instantiate()
_bull = (load("res://actors/player/player.tscn") as PackedScene).instantiate()
root.add_child(_bull)
_bull.global_position = Vector3(4, 1, 0)
_bear = (load("res://Bear.tscn") as PackedScene).instantiate()
_bear = (load("res://actors/bear/bear.tscn") as PackedScene).instantiate()
root.add_child(_bear)
_bear.global_position = Vector3(0, 1, 0)
await physics_frame
+1 -1
View File
@@ -27,7 +27,7 @@ func _ok(c: bool, m: String) -> void:
func _run() -> void:
var bear := (load("res://Bear.tscn") as PackedScene).instantiate()
var bear := (load("res://actors/bear/bear.tscn") as PackedScene).instantiate()
root.add_child(bear)
await physics_frame
+1 -1
View File
@@ -52,7 +52,7 @@ func _drive(bear: Node, fire: String) -> void:
func _run() -> void:
var bear := (load("res://Bear.tscn") as PackedScene).instantiate() as Node3D
var bear := (load("res://actors/bear/bear.tscn") as PackedScene).instantiate() as Node3D
root.add_child(bear)
bear.set_physics_process(false) # freeze the AI; we fire the colliders ourselves
await physics_frame
+1 -1
View File
@@ -56,7 +56,7 @@ func _ram_pass(bear: Node, bull: CharacterBody3D, speed: float, from: Vector3, t
func _run() -> void:
var bull := _make_bull()
var bear := (load("res://Bear.tscn") as PackedScene).instantiate() as Node3D
var bear := (load("res://actors/bear/bear.tscn") as PackedScene).instantiate() as Node3D
root.add_child(bear)
bear.global_position = Vector3.ZERO
bear.set_physics_process(false) # freeze the AI; we drive the ram sweep ourselves
+1 -1
View File
@@ -37,7 +37,7 @@ func _on_health(current: int, _max_hp: int) -> void:
func _run() -> void:
(root.get_node("/root/Run") as Node).call("ensure_run")
var scene: Node = load("res://scene.tscn").instantiate()
var scene: Node = load("res://levels/game_shell.tscn").instantiate()
root.add_child(scene)
current_scene = scene
await create_timer(0.8).timeout
+2 -2
View File
@@ -49,9 +49,9 @@ func _init() -> void:
func _run() -> void:
_dt = 1.0 / float(Engine.physics_ticks_per_second)
_dp = root.get_node_or_null("/root/DP")
_mat_scene = load("res://Matador.tscn") as PackedScene
_mat_scene = load("res://actors/matador/matador.tscn") as PackedScene
_scene = (load("res://scene.tscn") as PackedScene).instantiate()
_scene = (load("res://levels/game_shell.tscn") as PackedScene).instantiate()
root.add_child(_scene)
current_scene = _scene
await create_timer(0.5).timeout
+1 -1
View File
@@ -34,7 +34,7 @@ func _run() -> void:
_ok(missing == null, "unknown effect returns null instead of crashing")
# The preview gallery scene is wired (has its controller script + label).
var gallery: Node = load("res://fx/effect_gallery.tscn").instantiate()
var gallery: Node = load("res://systems/fx/effect_gallery.tscn").instantiate()
_ok(gallery.get_script() != null, "gallery scene keeps its controller script")
host.add_child(gallery)
await process_frame
+2 -2
View File
@@ -29,7 +29,7 @@ var _matador_scene: PackedScene = null
# preload of a matador scene compiles matador.gd before the DP autoload binds.
func _mat_scene() -> PackedScene:
if _matador_scene == null:
_matador_scene = load("res://Matador.tscn")
_matador_scene = load("res://actors/matador/matador.tscn")
return _matador_scene
@@ -40,7 +40,7 @@ func _init() -> void:
func _run() -> void:
DirAccess.make_dir_recursive_absolute(OUTPUT_DIR)
var scene_res := load("res://scene.tscn")
var scene_res := load("res://levels/game_shell.tscn")
if not scene_res:
push_error("gameplay_test: failed to load scene.tscn")
quit(1)
+1 -1
View File
@@ -44,7 +44,7 @@ func _run() -> void:
# Force the shell to build the Bear's Den regardless of the generated map.
run.debug_level_override = run.get_level(&"bear")
var scene: Node = load("res://scene.tscn").instantiate()
var scene: Node = load("res://levels/game_shell.tscn").instantiate()
root.add_child(scene)
current_scene = scene
# Let the shell instance the level and the spawner's deferred spawn run.
+1 -1
View File
@@ -377,7 +377,7 @@ func test_matador_state_transitions() -> void:
print("\n-- test_matador_state_transitions --")
# Verify that the State enum values match expected constants
# Load the matador scene to check its script
var matador_scene := load("res://Matador.tscn")
var matador_scene := load("res://actors/matador/matador.tscn")
if matador_scene == null:
_assert_true(false, "Matador.tscn should load")
return
+1 -1
View File
@@ -43,7 +43,7 @@ func _make_bull() -> CharacterBody3D:
func _make_matador(_bull: CharacterBody3D) -> CharacterBody3D:
var mat := (load("res://Matador.tscn") as PackedScene).instantiate() as CharacterBody3D
var mat := (load("res://actors/matador/matador.tscn") as PackedScene).instantiate() as CharacterBody3D
root.add_child(mat)
mat.global_position = Vector3.ZERO
mat.set_physics_process(false) # we drive the swept gore ourselves, isolated from the AI
+3 -3
View File
@@ -7,7 +7,7 @@ extends SceneTree
# physics_layers.gd is pure constants (safe to preload); spear_projectile.gd references the
# Settings autoload, whose global identifier isn't registered when a --script entry compiles its
# preloads — so it's loaded at runtime inside _run instead, once the autoloads exist.
const PhysicsLayers = preload("res://physics_layers.gd")
const PhysicsLayers = preload("res://systems/combat/physics_layers.gd")
var _pass := 0
var _fail := 0
@@ -44,8 +44,8 @@ func _run() -> void:
await physics_frame
# Launch a spear flat, dead-on from 3 m out; low gravity so the short flight stays level.
var spear_script := load("res://spear_projectile.gd")
var mesh := (load("res://Spear.tscn") as PackedScene).instantiate() as Node3D
var spear_script := load("res://actors/matador/spear_projectile.gd")
var mesh := (load("res://actors/matador/spear.tscn") as PackedScene).instantiate() as Node3D
root.add_child(mesh)
var origin := Vector3(0.0, 0.0, -3.0)
var spear := spear_script.launch(root, mesh, origin, Vector3(0.0, 0.0, 12.0), 0.05) as RigidBody3D
+1 -1
View File
@@ -45,7 +45,7 @@ func _run() -> void:
root.add_child(bull)
bull.global_position = Vector3(0.0, 0.0, standoff + 3.0)
var mat := (load("res://Matador.tscn") as PackedScene).instantiate() as CharacterBody3D
var mat := (load("res://actors/matador/matador.tscn") as PackedScene).instantiate() as CharacterBody3D
root.add_child(mat) # _ready acquires the bull from the "player" group
mat.global_position = Vector3.ZERO
mat.set_physics_process(false) # we drive the attack tick ourselves, isolated from the AI
+1 -1
View File
@@ -38,7 +38,7 @@ func _make_bull() -> CharacterBody3D:
func _make_taunting_matador(_bull: CharacterBody3D) -> CharacterBody3D:
var mat := (load("res://Matador.tscn") as PackedScene).instantiate() as CharacterBody3D
var mat := (load("res://actors/matador/matador.tscn") as PackedScene).instantiate() as CharacterBody3D
root.add_child(mat)
mat.global_position = Vector3.ZERO
mat.set_physics_process(false) # we drive _tick_wander ourselves, no brain
+1 -1
View File
@@ -45,7 +45,7 @@ func _run() -> void:
run.ensure_run()
run.debug_level_override = run.get_level(&"arena")
var scene: Node = load("res://scene.tscn").instantiate()
var scene: Node = load("res://levels/game_shell.tscn").instantiate()
root.add_child(scene)
current_scene = scene
+1 -1
View File
@@ -45,7 +45,7 @@ func _run() -> void:
run.ensure_run() # build the run first — the shell's own ensure_run would wipe the override
run.debug_level_override = run.get_level(&"arena")
var scene_res := load("res://scene.tscn")
var scene_res := load("res://levels/game_shell.tscn")
if not scene_res:
push_error("performance_test: failed to load scene.tscn")
quit(1)
+1 -1
View File
@@ -65,7 +65,7 @@ func _spawn_one() -> Node3D:
func _run() -> void:
# Warm up: first instance pays one-time import/JIT/shader costs that would skew sample 1.
_matador = load("res://Matador.tscn") as PackedScene
_matador = load("res://actors/matador/matador.tscn") as PackedScene
var warm := _spawn_one()
await process_frame
warm.call(&"apply_ability_hit", Vector3(1.0, 0.0, 0.0), 12.0)
+1 -1
View File
@@ -21,7 +21,7 @@ func _init() -> void:
func _run() -> void:
DirAccess.make_dir_recursive_absolute(OUTPUT_DIR)
var scene_res := load("res://scene.tscn")
var scene_res := load("res://levels/game_shell.tscn")
if not scene_res:
push_error("ragdoll_throw_test: failed to load scene.tscn")
quit(1)
+1 -1
View File
@@ -7,7 +7,7 @@ extends SceneTree
## hides the original skinned meshes (so they never hit the invisible-on-Mali skinning path).
## Run: godot --headless --script res://tests/rigid_skin_test.gd
const RigidSkin = preload("res://rigid_skin.gd")
const RigidSkin = preload("res://systems/render/rigid_skin.gd")
var _pass := 0
var _fail := 0
+1 -1
View File
@@ -18,7 +18,7 @@ func _run() -> void:
DirAccess.make_dir_recursive_absolute(OUTPUT_DIR)
# Load and switch to the main scene
var scene_res := load("res://scene.tscn")
var scene_res := load("res://levels/game_shell.tscn")
if scene_res == null:
push_error("screenshot_test: Failed to load scene.tscn")
quit(1)
+1 -1
View File
@@ -73,7 +73,7 @@ func _run() -> void:
# Headless boots a 64x64 root viewport, which collapses every UI rect on top of each other.
# Give it a real phone-ish landscape size so the joystick zone / buttons lay out sanely.
root.size = Vector2i(1152, 648)
_tc = (load("res://touch_controls.gd") as Script).new()
_tc = (load("res://systems/input/touch_controls.gd") as Script).new()
root.add_child(_tc)
await process_frame # _ready builds _surface and runs the first _relayout
_tc._relayout() # ensure the layout reflects the size set above
+2 -2
View File
@@ -145,7 +145,7 @@ func _find_touch(node: Node) -> Node:
func _boot_shell(touch: bool) -> Node:
var dp: Node = root.get_node("/root/DP")
dp.call("set_value", "force_touch_controls", touch)
var scene: Node = load("res://scene.tscn").instantiate()
var scene: Node = load("res://levels/game_shell.tscn").instantiate()
root.add_child(scene)
current_scene = scene
await create_timer(0.8).timeout # let the shell build the level + HUD
@@ -203,7 +203,7 @@ func _run() -> void:
# Short viewport so the rebind list can't fit, then open options the way the button does, so we
# measure the real panel laid out — not a hidden one whose scrollbar hasn't been computed yet.
root.size = Vector2i(1024, 600)
var menu: Node = load("res://MainMenu.tscn").instantiate()
var menu: Node = load("res://ui/main_menu.tscn").instantiate()
root.add_child(menu)
await create_timer(0.3).timeout
if menu.has_method("_on_options_pressed"):