From 6b189d7de1f62f115018fce02b0821ad39ec5b4a Mon Sep 17 00:00:00 2001 From: Pramod S Date: Mon, 31 Jul 2023 10:30:32 +0200 Subject: [PATCH 1/9] fixed layer button component issues mentioned in UX-1126 --- .../components/RevealToolbar/LayersButton.tsx | 136 +++++++++++++++++- .../CadModelLayersContainer.tsx | 61 ++++---- .../Image360LayersContainer.tsx | 40 +++--- .../LayersContainer/LayersContainer.tsx | 71 +++++++-- .../PointCloudLayersContainer.tsx | 48 ++++--- .../RevealToolbar/LayersContainer/types.ts | 40 ++++++ 6 files changed, 313 insertions(+), 83 deletions(-) create mode 100644 react-components/src/components/RevealToolbar/LayersContainer/types.ts diff --git a/react-components/src/components/RevealToolbar/LayersButton.tsx b/react-components/src/components/RevealToolbar/LayersButton.tsx index 8245db5bac9..4897529b385 100644 --- a/react-components/src/components/RevealToolbar/LayersButton.tsx +++ b/react-components/src/components/RevealToolbar/LayersButton.tsx @@ -2,25 +2,147 @@ * Copyright 2023 Cognite AS */ -import { type ReactElement, useState } from 'react'; +import React, { type ReactElement, useState, useEffect, useMemo, useRef } from 'react'; import { Button, Dropdown } from '@cognite/cogs.js'; -import { LayersContainer } from './LayersContainer/LayersContainer'; +import { type Reveal3DResourcesStates, type LayerStates } from './LayersContainer/types'; +import LayersContainer from './LayersContainer/LayersContainer'; +import { + type CognitePointCloudModel, + type CogniteCadModel, + type Image360Collection, + type CogniteModel +} from '@cognite/reveal'; +import { useReveal } from '../RevealContainer/RevealContext'; +import { use3DModelName } from '../../hooks/use3DModelName'; +import isEqual from 'lodash/isEqual'; export const LayersButton = (): ReactElement => { - const [layersEnabled, setLayersEnabled] = useState(false); + const layerStatesInitialState: LayerStates = { + allCadModelVisible: true, + cadIndeterminate: false, + allPointCloudModelVisible: true, + pointCloudIndeterminate: false, + allImages360Visible: true, + image360Indeterminate: false, + layersEnabled: false + }; + const viewer = useReveal(); + const [layerStates, setLayerStates] = useState(layerStatesInitialState); + + const [selectedCadModels] = useState< + Array<{ model: CogniteCadModel; isToggled: boolean; name?: string }> + >([]); + const [selectedPointCloudModels] = useState< + Array<{ model: CognitePointCloudModel; isToggled: boolean; name?: string }> + >([]); + const [selectedImage360Collection] = useState< + Array<{ image360: Image360Collection; isToggled: boolean }> + >([]); + + const [cadModelIds, setCadModelIds] = useState([]); + const [pointCloudModelIds, setPointCloudModelIds] = useState([]); + const prevModelsRef = useRef([]); + + const [reveal3DResources, setReveal3DResources] = useState({ + cadModels: selectedCadModels, + pointCloudModels: selectedPointCloudModels, + image360Collections: selectedImage360Collection + }); + const showLayers = (): void => { - setLayersEnabled(!layersEnabled); + setLayerStates((prevLayerStates) => ({ + ...prevLayerStates, + layersEnabled: !prevLayerStates.layersEnabled + })); }; + useEffect(() => { + const currentModels = viewer.models; + // Compare the previous and current models to avoid infinite loop + if (prevModelsRef.current !== currentModels) { + prevModelsRef.current = currentModels; + const cadIds = currentModels + .filter((model) => model.type === 'cad') + .map((model) => model.modelId); + const pointCloudIds = currentModels + .filter((model) => model.type === 'pointcloud') + .map((model) => model.modelId); + + // Only update the state when the modelIds change + if (!isEqual(cadModelIds, cadIds)) { + setCadModelIds(cadIds); + } + + if (!isEqual(pointCloudModelIds, pointCloudIds)) { + setPointCloudModelIds(pointCloudIds); + } + } + }, [viewer.models, cadModelIds, pointCloudModelIds]); + + const cadModelName = use3DModelName(cadModelIds); + const pointCloudModelName = use3DModelName(pointCloudModelIds); + + const updatedReveal3DResources: Reveal3DResourcesStates = useMemo(() => { + if (cadModelName.data === null && pointCloudModelName.data === null) { + return { + cadModels: [], + pointCloudModels: [], + image360Collections: [] + }; + } + const cadModels = viewer.models.filter((model) => model.type === 'cad'); + const pointCloudModels = viewer.models.filter((model) => model.type === 'pointcloud'); + const image360Collections = viewer.get360ImageCollections(); + + const updatedSelectedCadModels = cadModels.map((model, index) => ({ + model: model as CogniteCadModel, + isToggled: (model as CogniteCadModel).visible ?? true, + name: cadModelName?.data?.[index] ?? 'No model name' + })); + + const updatedSelectedPointCloudModel = pointCloudModels.map((model, index) => ({ + model: model as CognitePointCloudModel, + isToggled: (model as CognitePointCloudModel).getDefaultPointCloudAppearance().visible ?? true, + name: pointCloudModelName?.data?.[index] ?? 'No model name' + })); + + const updatedSelectedImage360Collection = image360Collections.map((image360Collection) => ({ + image360: image360Collection, + isToggled: true + })); + + return { + cadModels: updatedSelectedCadModels, + pointCloudModels: updatedSelectedPointCloudModel, + image360Collections: updatedSelectedImage360Collection + }; + }, [ + viewer.models.length, + viewer.get360ImageCollections().length, + cadModelName.data, + pointCloudModelName.data + ]); + + useEffect(() => { + setReveal3DResources(updatedReveal3DResources); + }, [updatedReveal3DResources]); + return ( } - visible={layersEnabled} + content={ + + } + visible={layerStates.layersEnabled} placement="auto">