diff --git a/scripts/lib/area-preview.js b/scripts/lib/area-preview.js
index ea7af1c..472ea41 100644
--- a/scripts/lib/area-preview.js
+++ b/scripts/lib/area-preview.js
@@ -50,6 +50,7 @@ function cesiumPreviewHtml(glbName, metadataName, routeName, vehicleModelName, a
+
diff --git a/scripts/lib/cesium-preview.js b/scripts/lib/cesium-preview.js
index 75e536b..5a08cfd 100644
--- a/scripts/lib/cesium-preview.js
+++ b/scripts/lib/cesium-preview.js
@@ -8,6 +8,7 @@
const toggleCruise = document.getElementById("toggleCruise");
const toggleFollow = document.getElementById("toggleFollow");
const toggleScene = document.getElementById("toggleScene");
+ const toggleBuildingGhost = document.getElementById("toggleBuildingGhost");
const toggleRoutes = document.getElementById("toggleRoutes");
const toggleVehicles = document.getElementById("toggleVehicles");
const toggleSignals = document.getElementById("toggleSignals");
@@ -287,8 +288,54 @@
const hasSemanticAssets = semanticAssets(assets).length > 0;
const sceneLabel = toggleScene.closest("label");
let viewMode = "scene";
+ let buildingGhostActive = false;
+
+ async function setBuildingGhost(enabled) {
+ const roads = assets.find((asset) => asset.id === "roads");
+ const buildings = assets.find((asset) => asset.id === "buildings");
+ const main = assets.find((asset) => asset.id === "main");
+ if (!roads || !buildings || !main) {
+ toggleBuildingGhost.checked = false;
+ toggleBuildingGhost.disabled = true;
+ return;
+ }
+ if (enabled) {
+ const loaded = await Promise.all([
+ loadAsset(viewer, roads, placement),
+ loadAsset(viewer, buildings, placement),
+ ]);
+ if (!loaded[0] || !loaded[1]) {
+ toggleBuildingGhost.checked = false;
+ setStatus("Building transparency unavailable");
+ return;
+ }
+ main.model.show = false;
+ roads.model.show = true;
+ buildings.model.show = true;
+ buildings.model.color = Cesium.Color.WHITE.withAlpha(0.22);
+ buildings.model.colorBlendMode = Cesium.ColorBlendMode.REPLACE;
+ buildings.model.colorBlendAmount = 1.0;
+ for (const asset of liveAssets(assets)) {
+ if (asset.id !== "main") asset.model.show = asset.category === "dynamic" || asset.category === "countdown"
+ ? toggleSignals.checked : asset.model.show;
+ }
+ buildingGhostActive = true;
+ setStatus("Buildings transparent");
+ } else {
+ for (const asset of semanticAssets(assets)) {
+ if (asset.model) asset.model.show = false;
+ }
+ main.model.show = toggleScene.checked;
+ for (const asset of liveAssets(assets)) {
+ if (asset.id !== "main") asset.model.show = toggleSignals.checked;
+ }
+ buildingGhostActive = false;
+ setStatus("Buildings opaque");
+ }
+ }
toggleScene.addEventListener("change", () => {
+ if (buildingGhostActive) return;
for (const asset of liveAssets(assets)) {
asset.model.show = toggleScene.checked;
if (asset.toggle) asset.toggle.checked = toggleScene.checked;
@@ -316,6 +363,13 @@
toggleDiagnostics.addEventListener("change", () => {
diagnosticsEl.classList.toggle("hidden", !toggleDiagnostics.checked);
});
+ toggleBuildingGhost.addEventListener("change", () => {
+ void setBuildingGhost(toggleBuildingGhost.checked);
+ });
+ if (!semanticAssets(assets).some((asset) => asset.id === "roads") ||
+ !semanticAssets(assets).some((asset) => asset.id === "buildings")) {
+ toggleBuildingGhost.disabled = true;
+ }
async function setViewMode(nextMode) {
if (nextMode === viewMode) return;
@@ -329,6 +383,10 @@
if (sceneLabel) sceneLabel.classList.toggle("hidden", inspecting);
if (!inspecting) {
+ if (buildingGhostActive) {
+ toggleBuildingGhost.checked = false;
+ await setBuildingGhost(false);
+ }
for (const asset of semanticAssets(assets)) {
if (asset.model) asset.model.show = false;
}
diff --git a/scripts/test-preview-assets.js b/scripts/test-preview-assets.js
index f99a321..4f2d646 100644
--- a/scripts/test-preview-assets.js
+++ b/scripts/test-preview-assets.js
@@ -124,6 +124,7 @@ assert.match(html, /"glbName":"scene\\u003c\\u0026\\u003e\.glb"/);
assert.match(html, /"vehicleModelNames":\["car-a\.gltf","truck-a\.gltf"\]/);
assert.match(html, /"trafficSignalsName":"traffic-signals\.json"/);
assert.match(html, /id="toggleSignals"/);
+assert.match(html, /id="toggleBuildingGhost"/);
assert.match(html, /id="viewMode"/);
assert.match(html, /data-view-mode="inspect"/);
assert.match(html, /id="semanticToggles" class="control-subgroup hidden"/);
@@ -137,6 +138,8 @@ assert.match(previewRuntime, /asset\.category === "dynamic"/);
assert.match(previewRuntime, /TrafficSignalDynamic_/);
assert.match(previewRuntime, /TrafficSignalDynamic_\$\{nodeKey\}_countdown_\$\{String\(value\)\.padStart\(2, "0"\)\}/);
assert.match(previewRuntime, /ColorBlendMode\.REPLACE/);
+assert.match(previewRuntime, /setBuildingGhost/);
+assert.match(previewRuntime, /buildings\.model\.color = Cesium\.Color\.WHITE\.withAlpha\(0\.22\)/);
assert.match(previewRuntime, /asset\.category === "countdown"/);
assert.doesNotMatch(previewRuntime, /createCountdownDigits/);
assert.doesNotMatch(previewRuntime, /digitMap/);