From e97539c935ab694bfe95ac658ec55624daf50143 Mon Sep 17 00:00:00 2001 From: "Christopher J. Tannum" Date: Fri, 25 Aug 2023 17:22:18 +0200 Subject: [PATCH] fix: changing default style does not update styling (#3613) * fix: changing default style does not update styling * fix: memoize filtered cad options --------- Co-authored-by: cognite-bulldozer[bot] <51074376+cognite-bulldozer[bot]@users.noreply.github.com> --- .../NodeCacheProvider/NodeCacheProvider.tsx | 6 +- .../Reveal3DResources/Reveal3DResources.tsx | 117 ++++++++---------- .../src/components/Reveal3DResources/types.ts | 18 ++- .../src/hooks/useCalculateModelsStyling.tsx | 87 +++++++------ .../stories/CadStylingCache.stories.tsx | 2 +- 5 files changed, 124 insertions(+), 106 deletions(-) diff --git a/react-components/src/components/NodeCacheProvider/NodeCacheProvider.tsx b/react-components/src/components/NodeCacheProvider/NodeCacheProvider.tsx index 6ba6ad1fea1..3fe04dbd0b9 100644 --- a/react-components/src/components/NodeCacheProvider/NodeCacheProvider.tsx +++ b/react-components/src/components/NodeCacheProvider/NodeCacheProvider.tsx @@ -22,7 +22,7 @@ export const FdmNodeCacheContext = createContext, - enabled: boolean + enabled = true ): UseQueryResult => { const content = useContext(FdmNodeCacheContext); @@ -81,7 +81,9 @@ export const useFdmAssetMappings = ( return useQuery( ['reveal', 'react-components', 'fdm-asset-mappings', fdmAssetExternalIds], async () => { - return await nodeCacheContent?.cache.getMappingsForFdmIds(fdmAssetExternalIds, models); + return ( + (await nodeCacheContent?.cache.getMappingsForFdmIds(fdmAssetExternalIds, models)) ?? [] + ); }, { enabled: fdmAssetExternalIds.length > 0 && models.length > 0, diff --git a/react-components/src/components/Reveal3DResources/Reveal3DResources.tsx b/react-components/src/components/Reveal3DResources/Reveal3DResources.tsx index f0296add674..aab81c2f020 100644 --- a/react-components/src/components/Reveal3DResources/Reveal3DResources.tsx +++ b/react-components/src/components/Reveal3DResources/Reveal3DResources.tsx @@ -1,7 +1,7 @@ /*! * Copyright 2023 Cognite AS */ -import { useRef, type ReactElement, useState, useEffect } from 'react'; +import { useRef, type ReactElement, useState, useEffect, useMemo } from 'react'; import { type Cognite3DViewer } from '@cognite/reveal'; import { CadModelContainer } from '../CadModelContainer/CadModelContainer'; import { type CadModelStyling } from '../CadModelContainer/useApplyCadModelStyling'; @@ -17,9 +17,10 @@ import { type TypedReveal3DModel, type AddResourceOptions, type Reveal3DResourcesProps, - type DefaultResourceStyling + type CadModelOptions, + type PointCloudModelOptions } from './types'; -import { useCalculateModelsStyling } from '../../hooks/useCalculateModelsStyling'; +import { useCalculateCadStyling } from '../../hooks/useCalculateModelsStyling'; export const Reveal3DResources = ({ resources, @@ -33,18 +34,27 @@ export const Reveal3DResources = ({ const numModelsLoaded = useRef(0); useEffect(() => { - getTypedModels(resources, viewer) - .then((models) => { - models.forEach((model) => { - setDefaultResourceStyling(model, defaultResourceStyling); - }); - return models; - }) - .then(setReveal3DModels) - .catch(console.error); + getTypedModels(resources, viewer).then(setReveal3DModels).catch(console.error); }, [resources, viewer]); - const reveal3DModelsStyling = useCalculateModelsStyling(reveal3DModels, instanceStyling ?? []); + const cadModelOptions = useMemo( + () => reveal3DModels.filter((model): model is CadModelOptions => model.type === 'cad'), + [reveal3DModels] + ); + + const pointCloudModelOptions = useMemo( + () => + reveal3DModels.filter( + (model): model is PointCloudModelOptions => model.type === 'pointcloud' + ), + [reveal3DModels] + ); + + const styledCadModelOptions = useCalculateCadStyling( + cadModelOptions, + instanceStyling ?? [], + defaultResourceStyling + ); const image360CollectionAddOptions = resources.filter( (resource): resource is AddImageCollection360Options => @@ -61,40 +71,38 @@ export const Reveal3DResources = ({ return ( <> - {reveal3DModels - .map((modelData, index) => ({ - ...modelData, - styling: reveal3DModelsStyling[index] as CadModelStyling - })) - .filter(({ type }) => type === 'cad') - .map((modelData, index) => { - return ( - - ); - })} - {reveal3DModels - .map((modelData, index) => ({ - ...modelData, - styling: reveal3DModelsStyling[index] as PointCloudModelStyling - })) - .filter(({ type }) => type === 'pointcloud') - .map((modelData, index) => { - return ( - - ); - })} + {styledCadModelOptions.map(({ styleGroups, model }, index) => { + const defaultStyle = model.styling?.default ?? defaultResourceStyling?.cad?.default; + const cadStyling: CadModelStyling = { + defaultStyle, + groups: styleGroups + }; + return ( + + ); + })} + {pointCloudModelOptions.map((pointCloudModelOptions, index) => { + const { modelId, revisionId, transform, styling } = pointCloudModelOptions; + const defaultStyle = styling?.default ?? defaultResourceStyling?.pointcloud?.default; + const pcStyling: PointCloudModelStyling = { + defaultStyle + }; + return ( + + ); + })} {image360CollectionAddOptions.map((addModelOption) => { return ( ; }; -export const useCalculateModelsStyling = ( - models: TypedReveal3DModel[], - instanceGroups: FdmAssetStylingGroup[] -): Array => { - const modelsMappedStyleGroups = useCalculateMappedStyling(models); +export type CadStyleGroup = NodeStylingGroup | TreeIndexStylingGroup; + +export type StyledModel = { + model: CadModelOptions; + styleGroups: CadStyleGroup[]; +}; + +export const useCalculateCadStyling = ( + models: CadModelOptions[], + instanceGroups: FdmAssetStylingGroup[], + defaultResourceStyling?: DefaultResourceStyling +): StyledModel[] => { + const modelsMappedStyleGroups = useCalculateMappedStyling( + models, + defaultResourceStyling?.cad?.mapped + ); const modelInstanceStyleGroups = useCalculateInstanceStyling(models, instanceGroups); console.log('Model instance style groups = ', modelInstanceStyleGroups); const joinedStyleGroups = useJoinStylingGroups( @@ -37,14 +51,13 @@ export const useCalculateModelsStyling = ( return joinedStyleGroups; }; -function useCalculateMappedStyling(models: TypedReveal3DModel[]): ModelStyleGroup[] { - const modelsRevisionsWithMappedEquipment = models.filter( - (model) => model.styling?.mapped !== undefined - ); - const shouldFetchAllMappedEquipment = modelsRevisionsWithMappedEquipment.length > 0; +function useCalculateMappedStyling( + models: CadModelOptions[], + defaultMappedNodeAppearance?: NodeAppearance +): ModelStyleGroup[] { + const modelsRevisionsWithMappedEquipment = useMemo(() => getMappedCadModelsOptions(), [models]); const { data: mappedEquipmentEdges } = useMappedEdgesForRevisions( - modelsRevisionsWithMappedEquipment, - shouldFetchAllMappedEquipment + modelsRevisionsWithMappedEquipment ); const modelsMappedStyleGroups = useMemo(() => { @@ -55,23 +68,28 @@ function useCalculateMappedStyling(models: TypedReveal3DModel[]): ModelStyleGrou ) { return []; } - - return models.map((model) => { + return modelsRevisionsWithMappedEquipment.map((model) => { const fdmData = mappedEquipmentEdges?.get(`${model.modelId}/${model.revisionId}`) ?? []; + const modelStyle = model.styling?.mapped ?? defaultMappedNodeAppearance; - const styleGroup = - model.styling?.mapped !== undefined - ? [getMappedStyleGroup(fdmData, model.styling.mapped)] - : []; + const styleGroup = modelStyle !== undefined ? [getMappedStyleGroup(fdmData, modelStyle)] : []; return { model, styleGroup }; }); - }, [models, mappedEquipmentEdges]); + }, [modelsRevisionsWithMappedEquipment, mappedEquipmentEdges, defaultMappedNodeAppearance]); return modelsMappedStyleGroups; + + function getMappedCadModelsOptions(): CadModelOptions[] { + if (defaultMappedNodeAppearance !== undefined) { + return models; + } + + return models.filter((model) => model.styling?.mapped !== undefined); + } } function useCalculateInstanceStyling( - models: TypedReveal3DModel[], + models: CadModelOptions[], instanceGroups: FdmAssetStylingGroup[] ): ModelStyleGroup[] { const { data: fdmAssetMappings } = useFdmAssetMappings( @@ -96,10 +114,10 @@ function useCalculateInstanceStyling( } function useJoinStylingGroups( - models: TypedReveal3DModel[], + models: CadModelOptions[], modelsMappedStyleGroups: ModelStyleGroup[], modelInstanceStyleGroups: ModelStyleGroup[] -): Array { +): StyledModel[] { const modelsStyling = useMemo(() => { if (modelInstanceStyleGroups.length === 0 && modelsMappedStyleGroups.length === 0) { return extractDefaultStyles(models); @@ -111,8 +129,8 @@ function useJoinStylingGroups( .filter((typedModel) => typedModel.model === model) .flatMap((typedModel) => typedModel.styleGroup); return { - defaultStyle: model.styling?.default, - groups: [...mappedStyleGroup, ...instanceStyleGroups] + model, + styleGroups: [...mappedStyleGroup, ...instanceStyleGroups] }; }); }, [models, modelInstanceStyleGroups, modelsMappedStyleGroups]); @@ -120,12 +138,11 @@ function useJoinStylingGroups( return modelsStyling; } -function extractDefaultStyles( - typedModels: TypedReveal3DModel[] -): Array { +function extractDefaultStyles(typedModels: CadModelOptions[]): StyledModel[] { return typedModels.map((model) => { return { - defaultStyle: model.styling?.default + model, + styleGroups: [] }; }); } @@ -144,7 +161,7 @@ function getMappedStyleGroup( function calculateCadModelStyling( stylingGroups: FdmAssetStylingGroup[], mappings: ThreeDModelMappings[], - model: TypedReveal3DModel + model: CadModelOptions ): TreeIndexStylingGroup[] { const modelMappings = getModelMappings(mappings, model); @@ -169,7 +186,7 @@ function getNodeSubtreeIndices(node: Node3D): TreeIndex[] { function getModelMappings( mappings: ThreeDModelMappings[], - model: TypedReveal3DModel + model: CadModelOptions ): Map { return mappings .filter( diff --git a/react-components/stories/CadStylingCache.stories.tsx b/react-components/stories/CadStylingCache.stories.tsx index 4efcc7547f4..176fa770f27 100644 --- a/react-components/stories/CadStylingCache.stories.tsx +++ b/react-components/stories/CadStylingCache.stories.tsx @@ -50,7 +50,7 @@ const Models = ({ addModelOptions }: CogniteCadModelProps): JSX.Element => { const [platformStyling, setPlatformStyling] = useState(); - const { data } = useMappedEdgesForRevisions([platformModelOptions], true); + const { data } = useMappedEdgesForRevisions([platformModelOptions]); const nodeIds = useMemo( () =>