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:
@@ -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
@@ -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
-1
@@ -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
-1
@@ -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)
|
||||
@@ -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 |
Reference in New Issue
Block a user