diff --git a/src/components/layout/ObjectInfo.vue b/src/components/layout/ObjectInfo.vue index d69a6cd..4a076f6 100644 --- a/src/components/layout/ObjectInfo.vue +++ b/src/components/layout/ObjectInfo.vue @@ -33,6 +33,12 @@ > FUNCTIONS +
+ +
runtime.handleObjectAction({ ...action }, value); const infoPanel = ref(null); +function handleHide() { + if (!selectedObjectGuid.value) return; + runtime.hideObjectByGuid(selectedObjectGuid.value); + runtime.deselectObject(); +} + const { isHovered } = useHover(infoPanel); watchEffect(() => { diff --git a/src/components/tools/display/DisplayGroup.vue b/src/components/tools/display/DisplayGroup.vue index 5182d46..e38797d 100644 --- a/src/components/tools/display/DisplayGroup.vue +++ b/src/components/tools/display/DisplayGroup.vue @@ -12,6 +12,7 @@ @delete="deleteSavedView" /> +
@@ -25,6 +26,7 @@ import { SaveViewButton, SavedViewsButton, SaveScreenshotButton, + ShowAllObjectsButton, } from "./index"; const SAVED_VIEWS_STORAGE_KEY = "compas_threejs_saved_views"; diff --git a/src/components/tools/display/ShowAllObjectsButton.vue b/src/components/tools/display/ShowAllObjectsButton.vue new file mode 100644 index 0000000..8e7ab87 --- /dev/null +++ b/src/components/tools/display/ShowAllObjectsButton.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/components/tools/display/index.ts b/src/components/tools/display/index.ts index b8a1e4c..d1299f5 100644 --- a/src/components/tools/display/index.ts +++ b/src/components/tools/display/index.ts @@ -1,3 +1,4 @@ export { default as SaveViewButton } from "./SaveViewButton.vue"; export { default as SavedViewsButton } from "./SavedViewsButton.vue"; export { default as SaveScreenshotButton } from "./SaveScreenshotButton.vue"; +export { default as ShowAllObjectsButton } from "./ShowAllObjectsButton.vue"; diff --git a/src/viewer/viewer_runtime.ts b/src/viewer/viewer_runtime.ts index f238a07..c7bc5ef 100644 --- a/src/viewer/viewer_runtime.ts +++ b/src/viewer/viewer_runtime.ts @@ -126,6 +126,7 @@ export class ViewerRuntime { private disposed = false; private pickedObject: THREE.Object3D | null = null; private pickedMaterial: THREE.Material | THREE.Material[] | null = null; + private readonly hiddenGuids = new Set(); private readonly highlightMaterial = new THREE.MeshStandardMaterial({ color: "orange", emissive: "yellow", @@ -279,6 +280,25 @@ export class ViewerRuntime { this.store.objectBarData.isVisible = false; } + hideObjectByGuid(guid: string): void { + const object = this.geometries.get(guid); + if (!object) return; + object.visible = false; + this.hiddenGuids.add(guid); + } + + showAllObjects(): void { + for (const guid of this.hiddenGuids) { + const object = this.geometries.get(guid); + if (object) object.visible = true; + } + this.hiddenGuids.clear(); + } + + deselectObject(): void { + this.clearPickedObject(); + } + setTransformMode(mode: "translate" | "rotate" | "scale"): void { this.store.pickerMode.value = mode; this.transformControls.setMode(mode); @@ -360,6 +380,7 @@ export class ViewerRuntime { this.disposeObject(object); } this.geometries.clear(); + this.hiddenGuids.clear(); this.clearLights(); for (const entry of this.materials.values()) entry.material.dispose(); this.materials.clear(); @@ -695,7 +716,10 @@ export class ViewerRuntime { } this.transformControls.attach(picked); const guid = this.findGeometryGuid(picked); - if (guid) this.sendData({ dispatch: "object_picked", guid }); + if (guid) { + this.store.selectedObjectGuid.value = guid; + this.sendData({ dispatch: "object_picked", guid }); + } } private clearPickedObject(): void { @@ -711,6 +735,7 @@ export class ViewerRuntime { this.transformControls.detach(); this.store.objectBarData.data = null; this.store.objectActionsState.splice(0); + this.store.selectedObjectGuid.value = null; } private findGeometryGuid(object: THREE.Object3D): string | undefined { @@ -813,6 +838,7 @@ export class ViewerRuntime { this.disposeObject(object); this.geometries.delete(guid); this.geometryMaterials.delete(guid); + this.hiddenGuids.delete(guid); } else if (data.type === "set_visibility") { object.visible = data.visible; } else if (data.type === "toggle_visibility") { @@ -1021,6 +1047,7 @@ export class ViewerRuntime { private resetAfterDispose(): void { for (const object of this.geometries.values()) this.disposeObject(object); this.geometries.clear(); + this.hiddenGuids.clear(); this.clearLights(); for (const entry of this.materials.values()) entry.material.dispose(); this.materials.clear(); diff --git a/src/viewer/viewer_store.ts b/src/viewer/viewer_store.ts index 26e0ea7..bd1384d 100644 --- a/src/viewer/viewer_store.ts +++ b/src/viewer/viewer_store.ts @@ -85,6 +85,7 @@ export interface ViewerStore { blockPicker: { value: boolean }; showEdges: { value: boolean }; theme: { value: "light" | "dark" }; + selectedObjectGuid: { value: string | null }; } export function createViewerStore(): ViewerStore { @@ -106,5 +107,6 @@ export function createViewerStore(): ViewerStore { blockPicker: reactive({ value: false }), showEdges: reactive({ value: false }), theme: reactive({ value: "light" as const }), + selectedObjectGuid: reactive({ value: null as string | null }), }; }