Give street props colliders, zoned placements and variants
Full build / Full desktop build + optional release (push) Successful in 4m2s
Full build / Import + headless tests (push) Successful in 31s

Props were decoration: the guard and guests walked straight through benches,
bins, bollards and planters. They now block movement and steer guests around.

Collision
- _add_prop_model() fits a StaticBody3D from the model's mesh bounds in
  holder-local space: a cylinder for bollard/bin/hydrant, a box otherwise, so
  placement rotation and variant scale carry over.
- Fallback primitives go through the same fit, so a missing .glb cannot silently
  remove collision.
- Each prop also publishes a NavigationObstacle3D; NpcAvatar enables agent
  avoidance and moves with the safe velocity from velocity_computed. The navmesh
  stays a flat walkable plane and avoidance does the steering.

Placement
- PROP_PLACEMENTS groups furniture by entrance, mid-block and curb zones, with a
  static placement_problems() validator for bounds, overlap/min-spacing,
  duplicates, and the door/steps/guest-lane exclusions.
- variant_for(index) gives deterministic yaw jitter, subtle scale, and optional
  clutter (bag by the bin, crate by the newspaper boxes, cone by the hydrant).

Verification
- New windowed smoke_props.gd: guard walks into a bench and stops; a guest
  headed beyond the bench routes around it and never enters the collider.
- Headless 182 -> 187: placement validation and its failure modes, variant
  determinism/range, collider + obstacle on every placed prop, fallback collider.
- Other smokes (PLAN verbs, crowd, emergency, timeline) still pass; Python
  tooling 53/53; screenshots recaptured; compare 9 good / 0 bad.
- Version 0.4.0. TODO: collision/placement section moved to DONE; prop pipeline
  checks remain.
This commit is contained in:
zwitschi committed 2026-11-01 10:16:53 +01:00
1 parent a3e90accdd
commit bb40a98537
18 files changed
+518 -66

No files matched your search

+25
View File
@@ -709,3 +709,28 @@ Python tooling **53/53**, headless **182/182**.
the reference matches the game camera.
- [x] Added `Hud.clear_log()` so staged captures drop target-cycling noise; the escalation shot
keeps the real reaction lines.
## Prop Collision And Placement
Completed 2026-11-01 (v0.4.0). Headless **187/187**, Python tooling **53/53**, the new
`smoke_props.gd` passes windowed, and `screen_designs.py compare` still reports 9 good / 0 bad.
- [x] Every generated prop now gets a fitted static collider: a cylinder for bollard, bin, and
hydrant, a box for everything else. The collider is computed from the model's mesh bounds in
holder-local space, so placement rotation and variant scale carry over.
- [x] Added `smoke_props.gd` (windowed): the guard walks into a bench and stops instead of passing
through it; a guest heading for a point beyond the same bench routes around it with
navigation avoidance and never ends up inside the collider.
- [x] Props publish a `NavigationObstacle3D` footprint, and `NpcAvatar` enables agent avoidance with
a `velocity_computed` callback. The navmesh stays a flat walkable plane; avoidance does the
steering around street furniture.
- [x] Replaced the hard-coded prop calls with `WorldBuilder.PROP_PLACEMENTS`, grouped by entrance,
mid-block, and curb zones, with a static `placement_problems()` validator for bounds,
overlap/min-spacing, duplicates, and the door/steps/guest-lane exclusions.
- [x] Deterministic variants per placement (`variant_for`): yaw jitter, subtle scale, and optional
procedural clutter (bag by the bin, crate by the newspaper boxes, cone by the hydrant), so
repeated props stop looking cloned.
- [x] Fallback primitive props go through the same bounds fit, so a missing `.glb` cannot silently
remove collision; a unit test covers the fallback body, shape, width, and navigation obstacle.
- [x] Tests: placement validation and its failure modes, variant determinism/range, colliders on
every placed prop (including obstacle presence), and the fallback collider path.