refactor(assets): move sprite renderer to standalone project at renderer/

Separates the 3D-to-2D render pipeline from the game client into its
own minimal Godot project. No autoloads, no plugins, no game code —
just the render scene, models, textures, and export script. Eliminates
SimBridge parse errors and gdUnit4 scanning during renders.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-12 23:26:16 +01:00
co-authored by Claude Opus 4.6
parent 8a1b10786f
commit 921d2aef0d
11 changed files with 38 additions and 20 deletions
+7 -8
View File
@@ -6,8 +6,7 @@ description: >
east, south, west) with outline applied at working resolution. Use when the
user says "render sprite", "render model", "run the render pipeline",
"test the pipeline", "/render-sprite", or asks to render a specific model
(e.g., "render wall_structural"). Output: 12 PNG files in
client/tooling/sprite_renderer/output/.
(e.g., "render wall_structural"). Output: 12 PNG files in renderer/output/.
---
## Render Pipeline
@@ -20,15 +19,15 @@ Run the render script with the model name:
### Available Models
Models live at `client/tooling/sprite_renderer/models/<name>.tscn`. List them:
Models live at `renderer/models/<name>.tscn`. List them:
```bash
ls client/tooling/sprite_renderer/models/*.tscn | xargs -I{} basename {} .tscn
ls renderer/models/*.tscn | xargs -I{} basename {} .tscn
```
### Output
12 files per model in `client/tooling/sprite_renderer/output/`:
12 files per model in `renderer/output/`:
```
<model>_north_1024.png <model>_north_256.png <model>_north_64.png
@@ -46,11 +45,11 @@ ls client/tooling/sprite_renderer/models/*.tscn | xargs -I{} basename {} .tscn
### Troubleshooting
- **No output files**: Godot needs a display. If running headless, prefix with `xvfb-run`.
- **Model not found**: Check the model .tscn exists in `models/` directory.
- **Model not found**: Check the model .tscn exists in `renderer/models/`.
- **Godot not found**: Pass path as second arg: `render.sh wall_structural /path/to/godot`
### Adding New Models
1. Create model scene at `client/tooling/sprite_renderer/models/<name>.tscn`
2. Apply texture from `textures/` via StandardMaterial3D
1. Create model scene at `renderer/models/<name>.tscn`
2. Apply texture from `renderer/textures/` via StandardMaterial3D
3. Run: `.claude/skills/render-sprite/scripts/render.sh <name>`
@@ -7,16 +7,16 @@ set -euo pipefail
MODEL_NAME="${1:?Usage: render.sh <model_name> [godot_path]}"
GODOT="${2:-$HOME/bin/godot}"
REPO_ROOT="$(cd "$(dirname "$0")" && git rev-parse --show-toplevel)"
PROJECT="$REPO_ROOT/client"
SCENE="res://tooling/sprite_renderer/render_scene.tscn"
OUTPUT="$PROJECT/tooling/sprite_renderer/output"
PROJECT="$REPO_ROOT/renderer"
SCENE="res://render_scene.tscn"
OUTPUT="$PROJECT/output"
# Verify model exists
MODEL_FILE="$PROJECT/tooling/sprite_renderer/models/${MODEL_NAME}.tscn"
MODEL_FILE="$PROJECT/models/${MODEL_NAME}.tscn"
if [ ! -f "$MODEL_FILE" ]; then
echo "ERROR: Model not found: $MODEL_FILE"
echo "Available models:"
ls "$PROJECT/tooling/sprite_renderer/models/"*.tscn 2>/dev/null | xargs -I{} basename {} .tscn
ls "$PROJECT/models/"*.tscn 2>/dev/null | xargs -I{} basename {} .tscn
exit 1
fi
+6 -1
View File
@@ -8,7 +8,12 @@ client/export/
client/reports/
client/**/*.import
client/**/*.uid
client/tooling/sprite_renderer/output/*.png
# Renderer (separate Godot project for sprite pipeline)
renderer/.godot/
renderer/**/*.import
renderer/**/*.uid
renderer/output/*.png
# Database (shared across worktrees at ../settledreach.db, not tracked)
db/commonwealth.db*
@@ -1,6 +1,6 @@
[gd_scene load_steps=3 format=3]
[ext_resource type="Texture2D" path="res://tooling/sprite_renderer/textures/wall_bar_green_panels.png" id="1_wall_texture"]
[ext_resource type="Texture2D" path="res://textures/wall_bar_green_panels.png" id="1_wall_texture"]
[sub_resource type="BoxMesh" id="BoxMesh_wall"]
size = Vector3(1.0, 0.8, 0.2)
@@ -1,6 +1,6 @@
[gd_scene load_steps=3 format=3 uid="uid://cyh0xf1nv2j3e"]
[ext_resource type="Texture2D" uid="uid://bgn5kvwjdqrx0" path="res://tooling/sprite_renderer/textures/wall_institutional_era1.png" id="1_wall_texture"]
[ext_resource type="Texture2D" path="res://textures/wall_institutional_era1.png" id="1_wall_texture"]
[sub_resource type="BoxMesh" id="BoxMesh_wall"]
size = Vector3(1.0, 0.8, 0.2)
+14
View File
@@ -0,0 +1,14 @@
; Sprite Renderer — standalone Godot project for 3D-to-2D sprite pipeline.
; No game logic, no autoloads, no plugins. Just rendering.
config_version=5
[application]
config/name="Settled Reach Sprite Renderer"
config/features=PackedStringArray("4.6", "GL Compatibility")
[rendering]
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility"
@@ -24,12 +24,12 @@ const ROTATIONS: PackedFloat64Array = [0.0, 90.0, 180.0, 270.0]
func _ready() -> void:
if Engine.is_editor_hint():
return
# CLI mode: godot --path client/ res://tooling/sprite_renderer/render_scene.tscn -- wall_structural
# CLI mode: godot --path client/ res://render_scene.tscn -- wall_structural
var args := OS.get_cmdline_user_args()
if args.size() == 0:
return
var model_name := args[0]
var model_path := "res://tooling/sprite_renderer/models/%s.tscn" % model_name
var model_path := "res://models/%s.tscn" % model_name
if not ResourceLoader.exists(model_path):
push_error("Model not found: %s" % model_path)
get_tree().quit(1)
@@ -59,7 +59,7 @@ func _execute_render() -> void:
model_root.add_child(model_instance)
# Ensure output directory exists
var output_dir := "res://tooling/sprite_renderer/output"
var output_dir := "res://output"
if not DirAccess.dir_exists_absolute(output_dir):
DirAccess.make_dir_recursive_absolute(output_dir)
@@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://cqvfv4uhbgq6h"]
[ext_resource type="Script" path="res://tooling/sprite_renderer/render_export.gd" id="1_render_script"]
[ext_resource type="Script" path="res://render_export.gd" id="1_render_script"]
[node name="RenderScene" type="Node3D"]
script = ExtResource("1_render_script")

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Before

Width:  |  Height:  |  Size: 991 KiB

After

Width:  |  Height:  |  Size: 991 KiB