Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api/scripts.fp.traffic.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions scripts/fp/traffic/junctions.gd
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ var lg: LG
var sim: CitySim
var clock: float = 0.0
var root: Node3D
## The quality preset's visibility scale (CityView.vis_mult), set by the traffic feature; the
## signal/sign GLBs are ranged with it at build time (street_dressing's _range convention).
var vis_mult: float = 1.0
## tile -> {"node": Node3D, "groups": Array[MeshInstance3D] (axis * 3 + colour), "peds":
## Array[GeometryInstance3D] per (axis * 2 + walk), "poles": Array[Node3D], "state": int,
## "colliders": Array of holder-local solid entries (written into the view's holder meta)}
Expand Down Expand Up @@ -326,6 +329,7 @@ func _build_cross(i: int) -> Dictionary:
var inst := _asset.instantiate() as Node3D
if inst != null:
pole.add_child(inst)
_range_asset(inst)
_bind_asset_lamps(inst, axis, groups)
_bind_asset_peds(inst, 1 - axis, ped_nodes)
continue
Expand Down Expand Up @@ -477,6 +481,19 @@ func _ped_signal(kit: KIT, at: Vector2, face: Vector2, hand: KIT, man: KIT) -> v
)


## The signal and sign GLBs arrive unranged: without this every lamp lens and sign face in the
## city drew at every distance (790 of 2732 draws on the day-10 draw census). Range them like the
## kit parts (_mi): VIS_PROP scaled by the quality preset, dithered out over half a metre.
func _range_asset(inst: Node3D) -> void:
for n in inst.find_children("*", "GeometryInstance3D", true, false):
var gi := n as GeometryInstance3D
if gi.visibility_range_end != 0.0:
continue
gi.visibility_range_end = WS.VIS_PROP * vis_mult
gi.visibility_range_end_margin = 0.5
gi.visibility_range_fade_mode = GeometryInstance3D.VISIBILITY_RANGE_FADE_SELF


## Binds H's traffic-light asset lamps (Signal_Red_*, Signal_Amber_*, Signal_Green_*) into the
## lamp groups: each node gets its own material_override on state changes.
func _bind_asset_lamps(inst: Node, axis: int, groups: Array) -> void:
Expand Down Expand Up @@ -518,6 +535,7 @@ func _build_tee(i: int, t: LG.TileInfo) -> Dictionary:
var inst := ps.instantiate() as Node3D
inst.transform = xf
node.add_child(inst)
_range_asset(inst)
else:
kit.cyl(xf, 0.045 * M, 0.045 * M, 2.55 * M, POLE_COL, 8)
var px := xf * Transform3D(Basis(), Vector3(0, 2.25 * M, 0.06 * M))
Expand Down
1 change: 1 addition & 0 deletions scripts/fp/traffic/traffic_feature.gd
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ func on_world_rebuilt() -> void:
peds.rebuild_all()
junctions.setup(lanes, _props_root)
junctions.clock = clock
junctions.vis_mult = ctx.view.vis_mult if ctx.view != null else 1.0
# Junction posts are solid: junctions writes their colliders into the view's holder meta and
# calls collision back; only this ctx holds the view and the collision world.
junctions.holder_of = func(i: int) -> Node3D:
Expand Down
64 changes: 64 additions & 0 deletions tools/tests/fp_junction_range_test.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
extends SceneTree
## The traffic-light and sign GLBs must leave junctions._range_asset ranged: unranged, every
## lamp lens and sign face in the city drew at every distance (790 of 2732 draws on the day-10
## draw census). The range follows the quality preset's vis_mult (the web tier's 0.55), and a
## node the asset pre-ranges is left alone.

const JN := preload("res://scripts/fp/traffic/junctions.gd")
const AP := preload("res://scripts/fp/asset_paths.gd")
const WS := preload("res://scripts/fp/world_scale.gd")

var _fail := 0


func _check(ok: bool, name: String) -> void:
if ok:
print("PASS ", name)
else:
_fail += 1
print("FAIL ", name)


func _initialize() -> void:
var jn: JN = JN.new()
jn.vis_mult = 0.55
var ps := AP.load_scene(AP.TRAFFIC_LIGHT)
_check(ps != null, "traffic light asset loads")
var inst := (ps as PackedScene).instantiate() as Node3D
root.add_child(inst)
var gis := inst.find_children("*", "GeometryInstance3D", true, false)
_check(gis.size() > 0, "the asset has geometry")
(gis[0] as GeometryInstance3D).visibility_range_end = 99.0
jn._range_asset(inst)
var want: float = WS.VIS_PROP * 0.55
var unranged := 0
var wrong := 0
for g in gis:
var gi := g as GeometryInstance3D
if gi.visibility_range_end == 0.0:
unranged += 1
elif (
absf(gi.visibility_range_end - want) > 0.01
and absf(gi.visibility_range_end - 99.0) > 0.01
):
wrong += 1
_check(unranged == 0, "every part ranged (%d unranged)" % unranged)
_check(wrong == 0, "ranges follow the preset scale (%.2f, %d wrong)" % [want, wrong])
_check(
absf((gis[0] as GeometryInstance3D).visibility_range_end - 99.0) < 0.01,
"a pre-ranged part keeps its own range"
)
_check(
(
(gis[1] as GeometryInstance3D).visibility_range_fade_mode
== GeometryInstance3D.VISIBILITY_RANGE_FADE_SELF
),
"parts fade out instead of popping"
)
inst.free()
if _fail == 0:
print("FP_JUNCTION_RANGE_TEST: PASS")
quit(0)
else:
print("FP_JUNCTION_RANGE_TEST: FAIL (", _fail, ")")
quit(1)
1 change: 1 addition & 0 deletions tools/tests/fp_junction_range_test.gd.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://bf0qd5pana6f6