Feat/visual audio overhaul #21
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
|
||||||
|
Nature Kit (2.1)
|
||||||
|
|
||||||
|
Created/distributed by Kenney (www.kenney.nl)
|
||||||
|
Creation date: 29-04-2020 01:02
|
||||||
|
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
License: (Creative Commons Zero, CC0)
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
|
||||||
|
This content is free to use in personal, educational and commercial projects.␍
|
||||||
|
Support us by crediting Kenney or www.kenney.nl (this is not mandatory)
|
||||||
|
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Donate: http://support.kenney.nl
|
||||||
|
Request: http://request.kenney.nl
|
||||||
|
Patreon: http://patreon.com/kenney/
|
||||||
|
|
||||||
|
Follow on Twitter for updates:
|
||||||
|
http://twitter.com/KenneyNL
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,36 @@
|
|||||||
|
extends SceneTree
|
||||||
|
|
||||||
|
## Dev tool: print AABBs of prop models used by the city builder.
|
||||||
|
|
||||||
|
const PATHS := [
|
||||||
|
"res://assets/props/roads/road-straight.glb",
|
||||||
|
"res://assets/props/roads/road-crossroad-line.glb",
|
||||||
|
"res://assets/props/roads/road-crossing.glb",
|
||||||
|
"res://assets/props/roads/light-curved.glb",
|
||||||
|
"res://assets/props/roads/light-curved-double.glb",
|
||||||
|
"res://assets/props/roads/construction-barrier.glb",
|
||||||
|
"res://assets/props/roads/construction-cone.glb",
|
||||||
|
"res://assets/props/nature/tree_default.glb",
|
||||||
|
"res://assets/props/nature/tree_detailed.glb",
|
||||||
|
"res://assets/props/nature/tree_oak.glb",
|
||||||
|
"res://assets/props/nature/tree_tall.glb",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
func _initialize() -> void:
|
||||||
|
for p in PATHS:
|
||||||
|
var scene = load(p)
|
||||||
|
if scene == null:
|
||||||
|
print("measure: FAILED ", p)
|
||||||
|
continue
|
||||||
|
var inst: Node3D = scene.instantiate()
|
||||||
|
get_root().add_child(inst)
|
||||||
|
var aabb := AABB()
|
||||||
|
var first := true
|
||||||
|
for mi in inst.find_children("*", "MeshInstance3D", true, false):
|
||||||
|
var b: AABB = mi.global_transform * mi.get_aabb()
|
||||||
|
aabb = b if first else aabb.merge(b)
|
||||||
|
first = false
|
||||||
|
print("measure: %s size=%s min=%s" % [p.get_file(), aabb.size, aabb.position])
|
||||||
|
inst.queue_free()
|
||||||
|
quit()
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://dd4g4l7mg66ro
|
||||||
@@ -134,9 +134,25 @@ func _kit_building(key: String, front_pos: Vector3, yaw_deg: float, node_name: S
|
|||||||
inst.scale = Vector3.ONE * scale_f
|
inst.scale = Vector3.ONE * scale_f
|
||||||
body.add_child(inst)
|
body.add_child(inst)
|
||||||
LevelMaterials.apply_toon_recursive(inst, 0.0)
|
LevelMaterials.apply_toon_recursive(inst, 0.0)
|
||||||
|
# Subtle per-building tint so repeated kit models read as different shops
|
||||||
|
_tint_recursive(inst, Color(1, 1, 1).lerp(Color.from_hsv(_rng.randf(), 0.3, 1.0), 0.16))
|
||||||
return w
|
return w
|
||||||
|
|
||||||
|
|
||||||
|
func _tint_recursive(node: Node, tint: Color) -> void:
|
||||||
|
if node is MeshInstance3D:
|
||||||
|
var mi := node as MeshInstance3D
|
||||||
|
var sc: int = mi.mesh.get_surface_count() if mi.mesh else 0
|
||||||
|
for s in sc:
|
||||||
|
var m := mi.get_surface_override_material(s)
|
||||||
|
if m is ShaderMaterial:
|
||||||
|
var c = m.get_shader_parameter("albedo_color")
|
||||||
|
if c is Color:
|
||||||
|
m.set_shader_parameter("albedo_color", c * tint)
|
||||||
|
for child in node.get_children():
|
||||||
|
_tint_recursive(child, tint)
|
||||||
|
|
||||||
|
|
||||||
## Fill one street-facing edge of a lot with kit buildings + Akiba signage.
|
## Fill one street-facing edge of a lot with kit buildings + Akiba signage.
|
||||||
func _kit_fill_side(front_x: float, dir: int, z0: float, z1: float, seed_id: String) -> void:
|
func _kit_fill_side(front_x: float, dir: int, z0: float, z1: float, seed_id: String) -> void:
|
||||||
var yaw := -90.0 if dir > 0 else 90.0 # face the street (-x for east row)
|
var yaw := -90.0 if dir > 0 else 90.0 # face the street (-x for east row)
|
||||||
@@ -252,6 +268,7 @@ func _build_geometry() -> void:
|
|||||||
_build_block(bx, bz)
|
_build_block(bx, bz)
|
||||||
|
|
||||||
_build_rail_line()
|
_build_rail_line()
|
||||||
|
_build_streets()
|
||||||
_build_avenues()
|
_build_avenues()
|
||||||
|
|
||||||
if _spawn_points.is_empty():
|
if _spawn_points.is_empty():
|
||||||
@@ -430,12 +447,14 @@ func _shrine_block(c: Vector3, bx: int, bz: int) -> void:
|
|||||||
# Hall with slide roof
|
# Hall with slide roof
|
||||||
_box_static(c + Vector3(0, 2.0, -10.0), Vector3(12.0, 4.0, 8.0), WOOD.darkened(0.2), n + "_Hall", "wood")
|
_box_static(c + Vector3(0, 2.0, -10.0), Vector3(12.0, 4.0, 8.0), WOOD.darkened(0.2), n + "_Hall", "wood")
|
||||||
_ramp_static(c + Vector3(0, 4.9, -8.2), Vector3(13.0, 0.3, 5.6), Vector3(-24, 0, 0), VERMILION.darkened(0.35), n + "_Roof", "wood")
|
_ramp_static(c + Vector3(0, 4.9, -8.2), Vector3(13.0, 0.3, 5.6), Vector3(-24, 0, 0), VERMILION.darkened(0.35), n + "_Roof", "wood")
|
||||||
# Stone lanterns + trees (trunk static, canopy deco)
|
# Stone lanterns + real modeled trees (trunk collider under each)
|
||||||
for i in 2:
|
for i in 2:
|
||||||
var lx := -8.0 + 16.0 * float(i)
|
var lx := -8.0 + 16.0 * float(i)
|
||||||
_box_static(c + Vector3(lx, 1.0, 8.0), Vector3(1.0, 2.0, 1.0), Color(0.55, 0.55, 0.52), n + "_Lant%d" % i, "brick")
|
_box_static(c + Vector3(lx, 1.0, 8.0), Vector3(1.0, 2.0, 1.0), Color(0.55, 0.55, 0.52), n + "_Lant%d" % i, "brick")
|
||||||
_box_static(c + Vector3(lx, 1.6, -2.0), Vector3(0.7, 3.2, 0.7), TRUNK, n + "_Trunk%d" % i, "wood")
|
_box_static(c + Vector3(lx, 1.6, -2.0), Vector3(0.8, 3.2, 0.8), TRUNK, n + "_Trunk%d" % i, "wood")
|
||||||
_deco_box(c + Vector3(lx, 4.6, -2.0), Vector3(4.2, 3.4, 4.2), LEAF)
|
_kit_prop_path("res://assets/props/nature/" + ["tree_detailed.glb", "tree_default.glb"][i % 2],
|
||||||
|
c + Vector3(lx, 0, -2.0), _rng.randf_range(0.0, 360.0), 7.0)
|
||||||
|
_kit_prop_path("res://assets/props/nature/tree_oak.glb", c + Vector3(0, 0, 2.0), _rng.randf_range(0.0, 360.0), 6.0)
|
||||||
_spawn_points.append(c + Vector3(0, 1.5, 12))
|
_spawn_points.append(c + Vector3(0, 1.5, 12))
|
||||||
|
|
||||||
|
|
||||||
@@ -470,12 +489,12 @@ func _market_block(c: Vector3, bx: int, bz: int) -> void:
|
|||||||
## Plaza: open ground; the exact centre cell hosts the giant screen tower.
|
## Plaza: open ground; the exact centre cell hosts the giant screen tower.
|
||||||
func _plaza_block(c: Vector3, bx: int, bz: int) -> void:
|
func _plaza_block(c: Vector3, bx: int, bz: int) -> void:
|
||||||
var n := "Plaza_%d_%d" % [bx, bz]
|
var n := "Plaza_%d_%d" % [bx, bz]
|
||||||
# Planter cover ring
|
# Planter cover ring with real trees
|
||||||
for i in 4:
|
for i in 4:
|
||||||
var a := TAU * float(i) / 4.0 + PI / 4.0
|
var a := TAU * float(i) / 4.0 + PI / 4.0
|
||||||
var p := c + Vector3(cos(a), 0, sin(a)) * (BLOCK * 0.32)
|
var p := c + Vector3(cos(a), 0, sin(a)) * (BLOCK * 0.32)
|
||||||
_box_static(Vector3(p.x, 0.55, p.z), Vector3(4.0, 1.1, 4.0), Color(0.5, 0.48, 0.52), "%s_Pl%d" % [n, i], "brick")
|
_box_static(Vector3(p.x, 0.55, p.z), Vector3(4.0, 1.1, 4.0), Color(0.5, 0.48, 0.52), "%s_Pl%d" % [n, i], "brick")
|
||||||
_deco_box(Vector3(p.x, 1.5, p.z), Vector3(3.2, 1.0, 3.2), LEAF)
|
_kit_prop_path("res://assets/props/nature/tree_oak.glb", Vector3(p.x, 1.0, p.z), float(i) * 90.0, 4.5)
|
||||||
# The Crossing screen tower on the single centre-most plaza cell
|
# The Crossing screen tower on the single centre-most plaza cell
|
||||||
if bx == 5 and bz == 4:
|
if bx == 5 and bz == 4:
|
||||||
_box_static(c + Vector3(0, 9.0, 0), Vector3(6.0, 18.0, 6.0), METAL.darkened(0.2), n + "_ScreenTower", "metal")
|
_box_static(c + Vector3(0, 9.0, 0), Vector3(6.0, 18.0, 6.0), METAL.darkened(0.2), n + "_ScreenTower", "metal")
|
||||||
@@ -511,6 +530,13 @@ func _construction_block(c: Vector3, bx: int, bz: int) -> void:
|
|||||||
for i in 3:
|
for i in 3:
|
||||||
_box_static(c + Vector3(10, 1.3 + 2.6 * float(mini(i, 1)), -12.0 + float(i) * 3.2), Vector3(6.2, 2.6, 2.6),
|
_box_static(c + Vector3(10, 1.3 + 2.6 * float(mini(i, 1)), -12.0 + float(i) * 3.2), Vector3(6.2, 2.6, 2.6),
|
||||||
cc[i], "%s_Cont%d" % [n, i], "metal")
|
cc[i], "%s_Cont%d" % [n, i], "metal")
|
||||||
|
# Cones + barriers scattered around the site entrance
|
||||||
|
for i in 4:
|
||||||
|
_kit_prop_path("res://assets/props/roads/construction-cone.glb",
|
||||||
|
c + Vector3(-16.0 + float(i) * 4.0, 0.1, 18.0), 0.0, 8.0)
|
||||||
|
for i in 2:
|
||||||
|
_kit_prop_path("res://assets/props/roads/construction-barrier.glb",
|
||||||
|
c + Vector3(-14.0 + float(i) * 12.0, 0.1, 14.0), float(i * 30), 8.0)
|
||||||
_spawn_points.append(c + Vector3(14, 1.5, -14))
|
_spawn_points.append(c + Vector3(14, 1.5, -14))
|
||||||
|
|
||||||
const INK_COLOR := Color(0.08, 0.07, 0.1)
|
const INK_COLOR := Color(0.08, 0.07, 0.1)
|
||||||
@@ -543,26 +569,110 @@ func _build_rail_line() -> void:
|
|||||||
_spawn_points.append(Vector3(0, RAIL_TOP + 1.5, z))
|
_spawn_points.append(Vector3(0, RAIL_TOP + 1.5, z))
|
||||||
|
|
||||||
|
|
||||||
# ── Main avenues: lights + crosswalks ────────────────────────────────────────
|
# ── Streets: real road meshes with markings ──────────────────────────────────
|
||||||
|
|
||||||
|
const ROAD_W := 12.0 # visual road width between sidewalk aprons
|
||||||
|
|
||||||
|
## Street lines run between block columns/rows at multiples of PITCH.
|
||||||
|
func _street_lines() -> Array[float]:
|
||||||
|
var lines: Array[float] = []
|
||||||
|
for i in GRID - 1:
|
||||||
|
lines.append((float(i) - float(GRID) * 0.5 + 1.0) * PITCH)
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
func _road_piece(key: String, pos: Vector3, yaw_deg: float, sc: Vector3) -> void:
|
||||||
|
var inst: Node3D = _kit_scene_at("res://assets/props/roads/" + key + ".glb").instantiate()
|
||||||
|
inst.scale = sc
|
||||||
|
add_child(inst)
|
||||||
|
inst.global_position = pos
|
||||||
|
inst.rotation_degrees.y = yaw_deg
|
||||||
|
LevelMaterials.apply_toon_recursive(inst, 0.0)
|
||||||
|
# The kit's pale concrete clips to white under the map lighting
|
||||||
|
_tint_recursive(inst, Color(0.55, 0.55, 0.6))
|
||||||
|
|
||||||
|
|
||||||
|
var _path_cache: Dictionary = {}
|
||||||
|
func _kit_scene_at(path: String) -> PackedScene:
|
||||||
|
if not _path_cache.has(path):
|
||||||
|
_path_cache[path] = load(path)
|
||||||
|
return _path_cache[path]
|
||||||
|
|
||||||
|
|
||||||
|
func _build_streets() -> void:
|
||||||
|
var lines := _street_lines()
|
||||||
|
var seg := PITCH - ROAD_W # straight run between intersections
|
||||||
|
var y := 0.02
|
||||||
|
# Intersections with line markings
|
||||||
|
for x in lines:
|
||||||
|
for z in lines:
|
||||||
|
_road_piece("road-crossroad-line", Vector3(x, y, z), 0.0, Vector3(ROAD_W, 2.0, ROAD_W))
|
||||||
|
# Straight segments (stretched single meshes) + edge stubs to the wall
|
||||||
|
for x in lines:
|
||||||
|
for i in lines.size() + 1:
|
||||||
|
var z0 := -CITY_HALF if i == 0 else lines[i - 1] + ROAD_W * 0.5
|
||||||
|
var z1 := CITY_HALF if i == lines.size() else lines[i] - ROAD_W * 0.5
|
||||||
|
if z1 - z0 < 2.0:
|
||||||
|
continue
|
||||||
|
_road_piece("road-straight", Vector3(x, y, (z0 + z1) * 0.5), 0.0, Vector3(ROAD_W, 2.0, z1 - z0))
|
||||||
|
for z in lines:
|
||||||
|
for i in lines.size() + 1:
|
||||||
|
var x0 := -CITY_HALF if i == 0 else lines[i - 1] + ROAD_W * 0.5
|
||||||
|
var x1 := CITY_HALF if i == lines.size() else lines[i] - ROAD_W * 0.5
|
||||||
|
if x1 - x0 < 2.0:
|
||||||
|
continue
|
||||||
|
_road_piece("road-straight", Vector3((x0 + x1) * 0.5, y, z), 90.0, Vector3(ROAD_W, 2.0, x1 - x0))
|
||||||
|
|
||||||
|
# Overhead cable bundles across east-west streets (urban-Japan clutter)
|
||||||
|
for z in lines:
|
||||||
|
var x := -CITY_HALF + 24.0
|
||||||
|
while x < CITY_HALF - 24.0:
|
||||||
|
if absf(x) > 14.0: # keep the central avenue sky clear
|
||||||
|
var h := 9.5 + fmod(absf(x), 3.0) * 0.4
|
||||||
|
for s3 in 3:
|
||||||
|
var t0 := float(s3) / 3.0
|
||||||
|
var t1 := float(s3 + 1) / 3.0
|
||||||
|
var sag0 := sin(t0 * PI) * 0.7
|
||||||
|
var sag1 := sin(t1 * PI) * 0.7
|
||||||
|
var za := z - STREET * 0.5 + STREET * t0
|
||||||
|
var zb := z - STREET * 0.5 + STREET * t1
|
||||||
|
var mid := Vector3(x, h - (sag0 + sag1) * 0.5, (za + zb) * 0.5)
|
||||||
|
_deco_box(mid, Vector3(0.07, 0.07, zb - za + 0.1), INK_COLOR)
|
||||||
|
x += 48.0
|
||||||
|
else:
|
||||||
|
x += 48.0
|
||||||
|
|
||||||
|
|
||||||
|
# ── Main avenues: kit streetlights ───────────────────────────────────────────
|
||||||
|
|
||||||
func _build_avenues() -> void:
|
func _build_avenues() -> void:
|
||||||
# The two central avenues (x=0 and z=0) get matched streetlights and
|
var lines := _street_lines()
|
||||||
# zebra crossings at every block line.
|
var lamp_scale := 10.0
|
||||||
var zline := -CITY_HALF + PITCH * 0.5
|
for z in lines:
|
||||||
while zline <= CITY_HALF:
|
|
||||||
for side: float in [-1.0, 1.0]:
|
for side: float in [-1.0, 1.0]:
|
||||||
var x := side * (STREET * 0.5 + 0.6)
|
# Double-arm lights along the central N-S avenue at every block line
|
||||||
_box_static(Vector3(x, 3.25, zline), Vector3(0.28, 6.5, 0.28), METAL, "LampA_%d_%d" % [int(zline), int(side)], "metal")
|
var x := side * (ROAD_W * 0.5 + 0.4)
|
||||||
_box_static(Vector3(x - side * 1.5, 6.35, zline), Vector3(3.0, 0.22, 0.22), METAL, "LampArmA_%d_%d" % [int(zline), int(side)], "metal")
|
_box_static(Vector3(x, 3.4, z), Vector3(0.26, 6.8, 0.26), METAL, "LampP_%d_%d" % [int(z), int(side)], "metal")
|
||||||
_deco_box(Vector3(x - side * 2.8, 6.2, zline), Vector3(0.9, 0.18, 0.4), Color(1.0, 0.95, 0.8), true)
|
_kit_prop_path("res://assets/props/roads/light-curved.glb",
|
||||||
# Crosswalk across the x=0 avenue at each block line
|
Vector3(x, 0, z), 90.0 if side > 0 else -90.0, lamp_scale)
|
||||||
for s in 5:
|
for x in lines:
|
||||||
var sxx := -6.0 + 3.0 * float(s)
|
if absf(x) < 1.0:
|
||||||
_deco_box(Vector3(sxx, 0.03, zline + PITCH * 0.5 - 4.0), Vector3(0.9, 0.06, 3.2), STRIPE)
|
continue
|
||||||
zline += PITCH
|
# Single lights down the central E-W avenue
|
||||||
var xline := -CITY_HALF + PITCH * 0.5
|
|
||||||
while xline <= CITY_HALF:
|
|
||||||
for side: float in [-1.0, 1.0]:
|
for side: float in [-1.0, 1.0]:
|
||||||
var z2 := side * (STREET * 0.5 + 0.6)
|
var z2 := side * (ROAD_W * 0.5 + 0.4)
|
||||||
_box_static(Vector3(xline, 3.25, z2), Vector3(0.28, 6.5, 0.28), METAL, "LampB_%d_%d" % [int(xline), int(side)], "metal")
|
_kit_prop_path("res://assets/props/roads/light-curved.glb",
|
||||||
xline += PITCH
|
Vector3(x, 0, z2), 0.0 if side > 0 else 180.0, lamp_scale)
|
||||||
|
|
||||||
|
|
||||||
|
func _kit_prop_path(path: String, pos: Vector3, yaw_deg: float, scale_f: float) -> void:
|
||||||
|
var inst: Node3D = _kit_scene_at(path).instantiate()
|
||||||
|
inst.scale = Vector3.ONE * scale_f
|
||||||
|
add_child(inst)
|
||||||
|
inst.global_position = pos
|
||||||
|
inst.rotation_degrees.y = yaw_deg
|
||||||
|
# Nature-kit foliage uses vertex-colored materials that the toon swap
|
||||||
|
# mangles (cyan trees) — keep original materials; the faceted low-poly
|
||||||
|
# look already reads cel under this lighting.
|
||||||
|
if not path.contains("/nature/"):
|
||||||
|
LevelMaterials.apply_toon_recursive(inst, 0.0)
|
||||||
|
|||||||
Reference in New Issue
Block a user