feat(preview): add transparent building mode

This commit is contained in:
2026-08-07 13:51:47 +08:00
parent 808266127d
commit 8237c7ed27
3 changed files with 62 additions and 0 deletions

View File

@@ -50,6 +50,7 @@ function cesiumPreviewHtml(glbName, metadataName, routeName, vehicleModelName, a
<button type="button" data-view-mode="inspect" aria-pressed="false">Inspect</button> <button type="button" data-view-mode="inspect" aria-pressed="false">Inspect</button>
</span> </span>
<label><input id="toggleScene" type="checkbox" checked> Scene</label> <label><input id="toggleScene" type="checkbox" checked> Scene</label>
<label><input id="toggleBuildingGhost" type="checkbox"> Building ghost</label>
<span id="assetToggles" class="control-subgroup"></span> <span id="assetToggles" class="control-subgroup"></span>
<span id="semanticToggles" class="control-subgroup hidden"></span> <span id="semanticToggles" class="control-subgroup hidden"></span>
<label><input id="toggleRoutes" type="checkbox" checked> Routes</label> <label><input id="toggleRoutes" type="checkbox" checked> Routes</label>

View File

@@ -8,6 +8,7 @@
const toggleCruise = document.getElementById("toggleCruise"); const toggleCruise = document.getElementById("toggleCruise");
const toggleFollow = document.getElementById("toggleFollow"); const toggleFollow = document.getElementById("toggleFollow");
const toggleScene = document.getElementById("toggleScene"); const toggleScene = document.getElementById("toggleScene");
const toggleBuildingGhost = document.getElementById("toggleBuildingGhost");
const toggleRoutes = document.getElementById("toggleRoutes"); const toggleRoutes = document.getElementById("toggleRoutes");
const toggleVehicles = document.getElementById("toggleVehicles"); const toggleVehicles = document.getElementById("toggleVehicles");
const toggleSignals = document.getElementById("toggleSignals"); const toggleSignals = document.getElementById("toggleSignals");
@@ -287,8 +288,54 @@
const hasSemanticAssets = semanticAssets(assets).length > 0; const hasSemanticAssets = semanticAssets(assets).length > 0;
const sceneLabel = toggleScene.closest("label"); const sceneLabel = toggleScene.closest("label");
let viewMode = "scene"; 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", () => { toggleScene.addEventListener("change", () => {
if (buildingGhostActive) return;
for (const asset of liveAssets(assets)) { for (const asset of liveAssets(assets)) {
asset.model.show = toggleScene.checked; asset.model.show = toggleScene.checked;
if (asset.toggle) asset.toggle.checked = toggleScene.checked; if (asset.toggle) asset.toggle.checked = toggleScene.checked;
@@ -316,6 +363,13 @@
toggleDiagnostics.addEventListener("change", () => { toggleDiagnostics.addEventListener("change", () => {
diagnosticsEl.classList.toggle("hidden", !toggleDiagnostics.checked); 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) { async function setViewMode(nextMode) {
if (nextMode === viewMode) return; if (nextMode === viewMode) return;
@@ -329,6 +383,10 @@
if (sceneLabel) sceneLabel.classList.toggle("hidden", inspecting); if (sceneLabel) sceneLabel.classList.toggle("hidden", inspecting);
if (!inspecting) { if (!inspecting) {
if (buildingGhostActive) {
toggleBuildingGhost.checked = false;
await setBuildingGhost(false);
}
for (const asset of semanticAssets(assets)) { for (const asset of semanticAssets(assets)) {
if (asset.model) asset.model.show = false; if (asset.model) asset.model.show = false;
} }

View File

@@ -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, /"vehicleModelNames":\["car-a\.gltf","truck-a\.gltf"\]/);
assert.match(html, /"trafficSignalsName":"traffic-signals\.json"/); assert.match(html, /"trafficSignalsName":"traffic-signals\.json"/);
assert.match(html, /id="toggleSignals"/); assert.match(html, /id="toggleSignals"/);
assert.match(html, /id="toggleBuildingGhost"/);
assert.match(html, /id="viewMode"/); assert.match(html, /id="viewMode"/);
assert.match(html, /data-view-mode="inspect"/); assert.match(html, /data-view-mode="inspect"/);
assert.match(html, /id="semanticToggles" class="control-subgroup hidden"/); 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_/);
assert.match(previewRuntime, /TrafficSignalDynamic_\$\{nodeKey\}_countdown_\$\{String\(value\)\.padStart\(2, "0"\)\}/); assert.match(previewRuntime, /TrafficSignalDynamic_\$\{nodeKey\}_countdown_\$\{String\(value\)\.padStart\(2, "0"\)\}/);
assert.match(previewRuntime, /ColorBlendMode\.REPLACE/); 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.match(previewRuntime, /asset\.category === "countdown"/);
assert.doesNotMatch(previewRuntime, /createCountdownDigits/); assert.doesNotMatch(previewRuntime, /createCountdownDigits/);
assert.doesNotMatch(previewRuntime, /digitMap/); assert.doesNotMatch(previewRuntime, /digitMap/);