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:
@@ -165,8 +165,17 @@ func spawn_prop_asset(asset_id: String, object_position: Vector2) -> PropBlock:
|
||||
if template.is_empty():
|
||||
push_warning("StageSpawner: unknown prop '%s'." % asset_id)
|
||||
return null
|
||||
var prop: PropBlock = PROP_UTILS.spawn_prop(_world, object_position, template["payload"], int(template["material_preset"]), Vector2.ZERO)
|
||||
prop.spawn_id = asset_id
|
||||
var prop: PropBlock
|
||||
if bool(template.get("is_custom", false)):
|
||||
prop = PROP_BLOCK.new()
|
||||
prop.name = "PropBlock"
|
||||
prop.position = object_position
|
||||
prop.material_preset = int(template["material_preset"])
|
||||
_world.add_child(prop)
|
||||
prop.set_custom_shapes(template.get("shapes", []) as Array[Dictionary], template.get("collision_hull", PackedVector2Array()) as PackedVector2Array)
|
||||
else:
|
||||
prop = PROP_UTILS.spawn_prop(_world, object_position, template["payload"], int(template["material_preset"]), Vector2.ZERO)
|
||||
prop.spawn_id = String(template.get("id", asset_id))
|
||||
return prop
|
||||
|
||||
|
||||
@@ -202,6 +211,12 @@ static func get_world_aabb(node: Node2D) -> Rect2:
|
||||
# Duck-typed TriggerArea: expose its centered local rect through the transform.
|
||||
if node.has_method("get_area_rect"):
|
||||
return node.global_transform * (node.call("get_area_rect") as Rect2)
|
||||
var visuals := node.get_node_or_null(NodePath("Visuals")) as Node2D
|
||||
if visuals != null:
|
||||
var visual_acc := { "min_x": INF, "min_y": INF, "max_x": -INF, "max_y": -INF }
|
||||
_collect_visual_points(visuals, visual_acc)
|
||||
if visual_acc["min_x"] <= visual_acc["max_x"]:
|
||||
return Rect2(Vector2(visual_acc["min_x"], visual_acc["min_y"]), Vector2(visual_acc["max_x"] - visual_acc["min_x"], visual_acc["max_y"] - visual_acc["min_y"]))
|
||||
var poly := node.get_node_or_null(NodePath("Polygon2D")) as Polygon2D
|
||||
if poly != null and not poly.polygon.is_empty():
|
||||
var rect := Rect2(node.to_global(poly.polygon[0]), Vector2.ZERO)
|
||||
|
||||
Reference in New Issue
Block a user