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
|
east, south, west) with outline applied at working resolution. Use when the
|
||||||
user says "render sprite", "render model", "run the render pipeline",
|
user says "render sprite", "render model", "run the render pipeline",
|
||||||
"test the pipeline", "/render-sprite", or asks to render a specific model
|
"test the pipeline", "/render-sprite", or asks to render a specific model
|
||||||
(e.g., "render wall_structural"). Output: 12 PNG files in
|
(e.g., "render wall_structural"). Output: 12 PNG files in renderer/output/.
|
||||||
client/tooling/sprite_renderer/output/.
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Render Pipeline
|
## Render Pipeline
|
||||||
@@ -20,15 +19,15 @@ Run the render script with the model name:
|
|||||||
|
|
||||||
### Available Models
|
### Available Models
|
||||||
|
|
||||||
Models live at `client/tooling/sprite_renderer/models/<name>.tscn`. List them:
|
Models live at `renderer/models/<name>.tscn`. List them:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ls client/tooling/sprite_renderer/models/*.tscn | xargs -I{} basename {} .tscn
|
ls renderer/models/*.tscn | xargs -I{} basename {} .tscn
|
||||||
```
|
```
|
||||||
|
|
||||||
### Output
|
### 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
|
<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
|
### Troubleshooting
|
||||||
|
|
||||||
- **No output files**: Godot needs a display. If running headless, prefix with `xvfb-run`.
|
- **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`
|
- **Godot not found**: Pass path as second arg: `render.sh wall_structural /path/to/godot`
|
||||||
|
|
||||||
### Adding New Models
|
### Adding New Models
|
||||||
|
|
||||||
1. Create model scene at `client/tooling/sprite_renderer/models/<name>.tscn`
|
1. Create model scene at `renderer/models/<name>.tscn`
|
||||||
2. Apply texture from `textures/` via StandardMaterial3D
|
2. Apply texture from `renderer/textures/` via StandardMaterial3D
|
||||||
3. Run: `.claude/skills/render-sprite/scripts/render.sh <name>`
|
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]}"
|
MODEL_NAME="${1:?Usage: render.sh <model_name> [godot_path]}"
|
||||||
GODOT="${2:-$HOME/bin/godot}"
|
GODOT="${2:-$HOME/bin/godot}"
|
||||||
REPO_ROOT="$(cd "$(dirname "$0")" && git rev-parse --show-toplevel)"
|
REPO_ROOT="$(cd "$(dirname "$0")" && git rev-parse --show-toplevel)"
|
||||||
PROJECT="$REPO_ROOT/client"
|
PROJECT="$REPO_ROOT/renderer"
|
||||||
SCENE="res://tooling/sprite_renderer/render_scene.tscn"
|
SCENE="res://render_scene.tscn"
|
||||||
OUTPUT="$PROJECT/tooling/sprite_renderer/output"
|
OUTPUT="$PROJECT/output"
|
||||||
|
|
||||||
# Verify model exists
|
# 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
|
if [ ! -f "$MODEL_FILE" ]; then
|
||||||
echo "ERROR: Model not found: $MODEL_FILE"
|
echo "ERROR: Model not found: $MODEL_FILE"
|
||||||
echo "Available models:"
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -8,7 +8,12 @@ client/export/
|
|||||||
client/reports/
|
client/reports/
|
||||||
client/**/*.import
|
client/**/*.import
|
||||||
client/**/*.uid
|
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)
|
# Database (shared across worktrees at ../settledreach.db, not tracked)
|
||||||
db/commonwealth.db*
|
db/commonwealth.db*
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[gd_scene load_steps=3 format=3]
|
[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"]
|
[sub_resource type="BoxMesh" id="BoxMesh_wall"]
|
||||||
size = Vector3(1.0, 0.8, 0.2)
|
size = Vector3(1.0, 0.8, 0.2)
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://cyh0xf1nv2j3e"]
|
[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"]
|
[sub_resource type="BoxMesh" id="BoxMesh_wall"]
|
||||||
size = Vector3(1.0, 0.8, 0.2)
|
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:
|
func _ready() -> void:
|
||||||
if Engine.is_editor_hint():
|
if Engine.is_editor_hint():
|
||||||
return
|
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()
|
var args := OS.get_cmdline_user_args()
|
||||||
if args.size() == 0:
|
if args.size() == 0:
|
||||||
return
|
return
|
||||||
var model_name := args[0]
|
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):
|
if not ResourceLoader.exists(model_path):
|
||||||
push_error("Model not found: %s" % model_path)
|
push_error("Model not found: %s" % model_path)
|
||||||
get_tree().quit(1)
|
get_tree().quit(1)
|
||||||
@@ -59,7 +59,7 @@ func _execute_render() -> void:
|
|||||||
model_root.add_child(model_instance)
|
model_root.add_child(model_instance)
|
||||||
|
|
||||||
# Ensure output directory exists
|
# 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):
|
if not DirAccess.dir_exists_absolute(output_dir):
|
||||||
DirAccess.make_dir_recursive_absolute(output_dir)
|
DirAccess.make_dir_recursive_absolute(output_dir)
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://cqvfv4uhbgq6h"]
|
[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"]
|
[node name="RenderScene" type="Node3D"]
|
||||||
script = ExtResource("1_render_script")
|
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