feat: Integrate custom prop library and sandbox functionality

- Added support for custom props in the sandbox, including loading, saving, and rendering.
- Implemented `PropLibrary` for managing custom prop entries and scanning for `.prop` files.
- Introduced `PropVisuals` for shared visual and collision representation of custom props.
- Enhanced `StageSpawner` to handle spawning of custom props with layered visuals and collision hulls.
- Created `MissingPropPlaceholder` to manage missing custom props during scene reloads.
- Updated thumbnail generation to support custom props with unique keys based on file paths.
- Added tests for custom prop lifecycle, authored visual values, and missing prop handling.
- Refactored existing code to accommodate new prop functionalities and ensure backward compatibility.
This commit is contained in:
2026-09-21 23:13:35 -04:00
parent 00abacc7b2
commit 97f3730413
19 changed files with 581 additions and 23 deletions
+15
View File
@@ -2,6 +2,7 @@ class_name PropThumbnail
extends Node
const PROP_BLOCK := preload("res://scripts/prop_block.gd")
const PROP_VISUALS := preload("res://scripts/prop_visuals.gd")
const SIZE := Vector2i(200, 200)
@@ -64,6 +65,20 @@ func render(payload: Dictionary, material_preset: int) -> Texture2D:
return ImageTexture.create_from_image(img)
func render_shapes(shapes: Array[Dictionary]) -> Texture2D:
_clear_world()
var visual := Node2D.new()
_world.add_child(visual)
var bounds: Rect2 = PROP_VISUALS.build(visual, shapes)
_frame_camera(bounds if bounds.size.length_squared() > 0.0 else Rect2(Vector2(-24, -24), Vector2(48, 48)))
await RenderingServer.frame_post_draw
await RenderingServer.frame_post_draw
var tex := _viewport.get_texture()
visual.queue_free()
if tex == null or _is_blank(tex.get_image()): return null
return ImageTexture.create_from_image(tex.get_image())
func _compute_points(payload: Dictionary) -> PackedVector2Array:
var shape_type: int = int(payload.get("type", PROP_BLOCK.ShapeType.POLYGON))
if shape_type == PROP_BLOCK.ShapeType.CIRCLE:
+3 -1
View File
@@ -40,7 +40,9 @@ func prop_png(id: String) -> String:
func prop_file_key(path: String) -> String:
return "%s_%d" % [path.get_file().get_basename(), FileAccess.get_modified_time(path)]
var canonical: String = path.simplify_path()
var digest: String = canonical.sha256_text().substr(0, 12)
return "file_%s_%d" % [digest, FileAccess.get_modified_time(path)]
func prop_file_png(path: String) -> String: