From b639f6829cce45869a9ab1a60f8c890c9a4a14a5 Mon Sep 17 00:00:00 2001 From: Nils Petter Fremming <35219649+nilscognite@users.noreply.github.com> Date: Tue, 28 May 2024 17:17:35 +0200 Subject: [PATCH] (feat) Make example code for training and some changes in the architecture (#4543) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial commit * Some movements * Fix linter problems * Make the axis a tiny better * Comments only * Some rafactoring * Make it better * Update MeasurementTool.ts * Fix lint * Make better axis tick labels, but still not perfect * handleEscape better * Changes in RevealRenderTarget * Update RootDomainObject.ts * Fix smal bug * Moving code * Fix typo * Set new default value * Fix typo * Initial commit * Update Architecture.stories.tsx * Update yarn.lock * Fix MeasureLineView so lines are visible from long distance * Make a DefaultRevealConfig * Add override keyword * Remove some unneccesary code * Update ExampleTool.ts * Update react-components/stories/Architecture.stories.tsx Co-authored-by: Håkon Flatval <70905152+haakonflatval-cognite@users.noreply.github.com> --------- Co-authored-by: Håkon Flatval <70905152+haakonflatval-cognite@users.noreply.github.com> --- .../architecture/base/commands/BaseTool.ts | 4 +- .../base/domainObjects/DomainObject.ts | 25 +++- .../base/domainObjectsHelpers/BaseDragger.ts | 3 +- .../base/domainObjectsHelpers/PopupStyle.ts | 13 ++ .../base/renderTarget/BaseRevealConfig.ts | 31 ++++ .../base/renderTarget/DefaultRevealConfig.ts | 7 + .../base/renderTarget/RevealRenderTarget.ts | 31 ++-- .../boxDomainObject/MeasureBoxDragger.ts | 2 +- .../boxDomainObject/MeasureDomainObject.ts | 2 +- .../boxDomainObject/MeasureLineRenderStyle.ts | 4 +- .../boxDomainObject/MeasureLineView.ts | 50 +++++-- .../boxDomainObject/MeasurementTool.ts | 24 ++-- .../concrete/config/StoryBookConfig.ts | 46 ++++++ .../ExampleDomainObject.ts | 105 ++++++++++++++ .../exampleDomainObject/ExampleDragger.ts | 49 +++++++ .../exampleDomainObject/ExampleRenderStyle.ts | 23 +++ .../exampleDomainObject/ExampleTool.ts | 133 ++++++++++++++++++ .../exampleDomainObject/ExampleView.ts | 111 +++++++++++++++ .../commands/DeleteAllExamplesCommand.ts | 40 ++++++ .../commands/ResetAllExamplesCommand.ts | 39 +++++ .../commands/ShowAllExamplesCommand.ts | 50 +++++++ .../Architecture/DomainObjectPanel.tsx | 28 ++-- .../components/Architecture/ToolButtons.tsx | 4 - .../{ActiveToolToolbar.tsx => Toolbar.tsx} | 53 +++++-- react-components/src/index.ts | 2 +- .../stories/Architecture.stories.tsx | 35 +---- .../utilities/RevealStoryContainer.tsx | 3 +- 27 files changed, 817 insertions(+), 100 deletions(-) create mode 100644 react-components/src/architecture/base/renderTarget/BaseRevealConfig.ts create mode 100644 react-components/src/architecture/base/renderTarget/DefaultRevealConfig.ts create mode 100644 react-components/src/architecture/concrete/config/StoryBookConfig.ts create mode 100644 react-components/src/architecture/concrete/exampleDomainObject/ExampleDomainObject.ts create mode 100644 react-components/src/architecture/concrete/exampleDomainObject/ExampleDragger.ts create mode 100644 react-components/src/architecture/concrete/exampleDomainObject/ExampleRenderStyle.ts create mode 100644 react-components/src/architecture/concrete/exampleDomainObject/ExampleTool.ts create mode 100644 react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts create mode 100644 react-components/src/architecture/concrete/exampleDomainObject/commands/DeleteAllExamplesCommand.ts create mode 100644 react-components/src/architecture/concrete/exampleDomainObject/commands/ResetAllExamplesCommand.ts create mode 100644 react-components/src/architecture/concrete/exampleDomainObject/commands/ShowAllExamplesCommand.ts rename react-components/src/components/Architecture/{ActiveToolToolbar.tsx => Toolbar.tsx} (59%) diff --git a/react-components/src/architecture/base/commands/BaseTool.ts b/react-components/src/architecture/base/commands/BaseTool.ts index af3ca3a4b20..cf09e2cb230 100644 --- a/react-components/src/architecture/base/commands/BaseTool.ts +++ b/react-components/src/architecture/base/commands/BaseTool.ts @@ -55,8 +55,8 @@ export abstract class BaseTool extends RenderTargetCommand { return 'default'; } - public getToolbar(): Array | undefined { - return undefined; // Override this to add extra buttons to a separate toolbar + public getToolbar(): Array { + return []; // Override this to add extra buttons to a separate toolbar } public getToolbarStyle(): PopupStyle { diff --git a/react-components/src/architecture/base/domainObjects/DomainObject.ts b/react-components/src/architecture/base/domainObjects/DomainObject.ts index ec7db29f776..591d554faf5 100644 --- a/react-components/src/architecture/base/domainObjects/DomainObject.ts +++ b/react-components/src/architecture/base/domainObjects/DomainObject.ts @@ -17,6 +17,7 @@ import { BLACK_COLOR, WHITE_COLOR } from '../utilities/colors/colorExtensions'; import { Views } from '../domainObjectsHelpers/Views'; import { type PanelInfo } from '../domainObjectsHelpers/PanelInfo'; import { PopupStyle } from '../domainObjectsHelpers/PopupStyle'; +import { RootDomainObject } from './RootDomainObject'; /** * Represents an abstract base class for domain objects. @@ -242,6 +243,22 @@ export abstract class DomainObject { */ protected notifyCore(change: DomainObjectChange): void { this.views.notify(this, change); + + // This is a little bit dirty, but will be refacored by using onIdle() + if ( + change.isChanged( + Changes.visibleState, + Changes.active, + Changes.active, + Changes.selected, + Changes.childAdded, + Changes.childDeleted + ) + ) { + if (this.root instanceof RootDomainObject) { + this.root.renderTarget.toolController.update(); + } + } } // ================================================== @@ -663,10 +680,12 @@ export abstract class DomainObject { return true; } - public removeInteractive(): void { - // You may call canBeDeleted() before calling this + public removeInteractive(checkCanBeDeleted = true): void { + if (checkCanBeDeleted && !this.canBeRemoved) { + return; + } for (const child of this.children) { - child.removeInteractive(); + child.removeInteractive(false); // If parent can be removed, so the children also } const { parent } = this; this.notify(Changes.deleted); diff --git a/react-components/src/architecture/base/domainObjectsHelpers/BaseDragger.ts b/react-components/src/architecture/base/domainObjectsHelpers/BaseDragger.ts index aee6d3481c9..b9f88196d92 100644 --- a/react-components/src/architecture/base/domainObjectsHelpers/BaseDragger.ts +++ b/react-components/src/architecture/base/domainObjectsHelpers/BaseDragger.ts @@ -23,6 +23,7 @@ export abstract class BaseDragger { // ================================================== protected constructor(props: CreateDraggerProps) { + // Note: that yje point and the ray comes in CDF coordinates this.point = props.point; this.ray = props.ray; } @@ -38,7 +39,7 @@ export abstract class BaseDragger { } // This must be overriden - // Notte that the ray comes in CDF coordinates + // Note: that the ray comes in CDF coordinates public abstract onPointerDrag(_event: PointerEvent, ray: Ray): boolean; public onPointerUp(_event: PointerEvent): void { diff --git a/react-components/src/architecture/base/domainObjectsHelpers/PopupStyle.ts b/react-components/src/architecture/base/domainObjectsHelpers/PopupStyle.ts index 2da9a0998d4..2f3a2fcdb73 100644 --- a/react-components/src/architecture/base/domainObjectsHelpers/PopupStyle.ts +++ b/react-components/src/architecture/base/domainObjectsHelpers/PopupStyle.ts @@ -4,6 +4,7 @@ */ type PopupProps = { + horizontal?: boolean; left?: number; right?: number; top?: number; @@ -13,6 +14,7 @@ type PopupProps = { }; export class PopupStyle { + private readonly _horizontal: boolean = true; private readonly _left?: number = undefined; private readonly _right?: number = undefined; private readonly _top?: number = undefined; @@ -21,6 +23,9 @@ export class PopupStyle { private readonly _padding: number = 16; // margin inside the popup public constructor(props: PopupProps) { + if (props.horizontal !== undefined) { + this._horizontal = props.horizontal; + } this._left = props.left; this._right = props.right; this._top = props.top; @@ -33,6 +38,14 @@ export class PopupStyle { } } + public get flexFlow(): string { + return this._horizontal ? 'row' : 'column'; + } + + public get isDividerHorizontal(): boolean { + return !this._horizontal; + } + public get leftPx(): string { return PopupStyle.getStringWithPx(this._left); } diff --git a/react-components/src/architecture/base/renderTarget/BaseRevealConfig.ts b/react-components/src/architecture/base/renderTarget/BaseRevealConfig.ts new file mode 100644 index 00000000000..1ae5fca1d75 --- /dev/null +++ b/react-components/src/architecture/base/renderTarget/BaseRevealConfig.ts @@ -0,0 +1,31 @@ +/*! + * Copyright 2024 Cognite AS + */ + +import { type AxisGizmoTool } from '@cognite/reveal/tools'; +import { type BaseCommand } from '../commands/BaseCommand'; +import { PopupStyle } from '../domainObjectsHelpers/PopupStyle'; +import { NavigationTool } from '../commands/NavigationTool'; +import { type BaseTool } from '../commands/BaseTool'; + +export abstract class BaseRevealConfig { + // ================================================== + // VIRTUAL METHODS: Override these to config the viewer + // ================================================== + + public createMainToolbar(): Array { + return []; + } + + public createMainToolbarStyle(): PopupStyle { + return new PopupStyle({ right: 0, top: 0, horizontal: false }); + } + + public createAxisGizmoTool(): AxisGizmoTool | undefined { + return undefined; + } + + public createDefaultTool(): BaseTool { + return new NavigationTool(); + } +} diff --git a/react-components/src/architecture/base/renderTarget/DefaultRevealConfig.ts b/react-components/src/architecture/base/renderTarget/DefaultRevealConfig.ts new file mode 100644 index 00000000000..76bd51afdf1 --- /dev/null +++ b/react-components/src/architecture/base/renderTarget/DefaultRevealConfig.ts @@ -0,0 +1,7 @@ +/*! + * Copyright 2024 Cognite AS + */ + +import { BaseRevealConfig } from './BaseRevealConfig'; + +export class DefaultRevealConfig extends BaseRevealConfig {} diff --git a/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts b/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts index 447039d1596..6bac37e06ad 100644 --- a/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts +++ b/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts @@ -9,7 +9,6 @@ import { type Cognite3DViewer, type IFlexibleCameraManager } from '@cognite/reveal'; -import { NavigationTool } from '../commands/NavigationTool'; import { Vector3, AmbientLight, @@ -26,7 +25,9 @@ import { getResizeCursor } from '../utilities/geometry/getResizeCursor'; import { VisualDomainObject } from '../domainObjects/VisualDomainObject'; import { ThreeView } from '../views/ThreeView'; import { type DomainObject } from '../domainObjects/DomainObject'; -import { AxisGizmoTool } from '@cognite/reveal/tools'; +import { type AxisGizmoTool } from '@cognite/reveal/tools'; +import { type BaseRevealConfig } from './BaseRevealConfig'; +import { DefaultRevealConfig } from './DefaultRevealConfig'; const DIRECTIONAL_LIGHT_NAME = 'DirectionalLight'; @@ -43,6 +44,7 @@ export class RevealRenderTarget { private _cropBoxBoundingBox: Box3 | undefined; private _cropBoxName: string | undefined = undefined; private _axisGizmoTool: AxisGizmoTool | undefined; + private _config: BaseRevealConfig | undefined = undefined; // ================================================== // CONTRUCTORS @@ -63,10 +65,7 @@ export class RevealRenderTarget { this._viewer.on('cameraChange', this.cameraChangeHandler); this._viewer.on('beforeSceneRendered', this.beforeSceneRenderedHandler); - const navigationTool = new NavigationTool(); - navigationTool.attach(this); - this.toolController.add(navigationTool); - this.toolController.setDefaultTool(navigationTool); + this.setConfig(new DefaultRevealConfig()); } // ================================================== @@ -77,6 +76,10 @@ export class RevealRenderTarget { return this._viewer; } + public get config(): BaseRevealConfig | undefined { + return this._config; + } + public get rootDomainObject(): RootDomainObject { return this._rootDomainObject; } @@ -129,9 +132,19 @@ export class RevealRenderTarget { // INSTANCE METHODS // ================================================== - public addAxisGizmo(): void { - this._axisGizmoTool = new AxisGizmoTool(); - this._axisGizmoTool.connect(this._viewer); + public setConfig(config: BaseRevealConfig): void { + this._config = config; + + const defaultTool = config.createDefaultTool(); + defaultTool.attach(this); + this.toolController.add(defaultTool); + this.toolController.setDefaultTool(defaultTool); + + const axisGizmoTool = config.createAxisGizmoTool(); + if (axisGizmoTool !== undefined) { + axisGizmoTool.connect(this._viewer); + this._axisGizmoTool = axisGizmoTool; + } } public dispose(): void { diff --git a/react-components/src/architecture/concrete/boxDomainObject/MeasureBoxDragger.ts b/react-components/src/architecture/concrete/boxDomainObject/MeasureBoxDragger.ts index 69723791092..f81638ede4a 100644 --- a/react-components/src/architecture/concrete/boxDomainObject/MeasureBoxDragger.ts +++ b/react-components/src/architecture/concrete/boxDomainObject/MeasureBoxDragger.ts @@ -83,7 +83,7 @@ export class MeasureBoxDragger extends BaseDragger { // OVERRIDES // ================================================== - public get domainObject(): DomainObject { + public override get domainObject(): DomainObject { return this._domainObject; } diff --git a/react-components/src/architecture/concrete/boxDomainObject/MeasureDomainObject.ts b/react-components/src/architecture/concrete/boxDomainObject/MeasureDomainObject.ts index 0f5cd6f5434..200efd6cd99 100644 --- a/react-components/src/architecture/concrete/boxDomainObject/MeasureDomainObject.ts +++ b/react-components/src/architecture/concrete/boxDomainObject/MeasureDomainObject.ts @@ -47,7 +47,7 @@ export abstract class MeasureDomainObject extends VisualDomainObject { } public override getPanelInfoStyle(): PopupStyle { - // bottom = 66 because the measurement toolbar is below + // bottom = 66 because the toolbar is below return new PopupStyle({ bottom: 66, left: 0 }); } diff --git a/react-components/src/architecture/concrete/boxDomainObject/MeasureLineRenderStyle.ts b/react-components/src/architecture/concrete/boxDomainObject/MeasureLineRenderStyle.ts index 729ec22e9f4..d1a12125ed8 100644 --- a/react-components/src/architecture/concrete/boxDomainObject/MeasureLineRenderStyle.ts +++ b/react-components/src/architecture/concrete/boxDomainObject/MeasureLineRenderStyle.ts @@ -11,8 +11,8 @@ export class MeasureLineRenderStyle extends MeasureRenderStyle { // INSTANCE FIELDS // ================================================== - public lineWidth = 2; - public pipeRadius = 0.03; + public pipeRadius = 0.015; + public lineWidth = 1; public selectedLineWidth = 2; // ================================================== diff --git a/react-components/src/architecture/concrete/boxDomainObject/MeasureLineView.ts b/react-components/src/architecture/concrete/boxDomainObject/MeasureLineView.ts index c4017d62a3d..c60287d628f 100644 --- a/react-components/src/architecture/concrete/boxDomainObject/MeasureLineView.ts +++ b/react-components/src/architecture/concrete/boxDomainObject/MeasureLineView.ts @@ -4,8 +4,12 @@ /* eslint-disable @typescript-eslint/consistent-type-imports */ import { + BufferAttribute, + BufferGeometry, CylinderGeometry, FrontSide, + Line, + LineBasicMaterial, Mesh, MeshPhongMaterial, Quaternion, @@ -73,7 +77,8 @@ export class MeasureLineView extends GroupThreeView { // ================================================== protected override addChildren(): void { - this.addChild(this.createCylinders()); + this.addChild(this.createPipe()); + this.addChild(this.createLines()); // Create a line so it can be seen from long distance this.addLabels(); } @@ -91,17 +96,17 @@ export class MeasureLineView extends GroupThreeView { // INSTANCE METHODS: // ================================================== - private createCylinders(): Mesh | undefined { + private createPipe(): Mesh | undefined { const { domainObject, style } = this; + const radius = style.pipeRadius; + if (radius <= 0) { + return; + } const { points } = domainObject; const { length } = points; if (length < 2) { return undefined; } - const radius = style.pipeRadius; - if (radius <= 0) { - return; - } const geometries: CylinderGeometry[] = []; const loopLength = domainObject.measureType === MeasureType.Polygon ? length + 1 : length; @@ -138,17 +143,20 @@ export class MeasureLineView extends GroupThreeView { return new Mesh(mergeGeometries(geometries, false), material); } - private createLines(): Wireframe | undefined { + private createWireframe(): Wireframe | undefined { const { domainObject, style } = this; + const linewidth = domainObject.isSelected ? style.selectedLineWidth : style.lineWidth; + if (linewidth === 0) { + return undefined; + } const vertices = createVertices(domainObject); if (vertices === undefined) { return undefined; } const color = domainObject.getColorByColorType(style.colorType); - const linewidth = domainObject.isSelected ? style.selectedLineWidth : style.lineWidth; const geometry = new LineSegmentsGeometry().setPositions(vertices); const material = new LineMaterial({ - linewidth: linewidth / 50, + linewidth, color, resolution: new Vector2(1000, 1000), worldUnits: true, @@ -157,6 +165,30 @@ export class MeasureLineView extends GroupThreeView { return new Wireframe(geometry, material); } + private createLines(): Line | undefined { + const { domainObject, style } = this; + const vertices = createVertices(domainObject); + if (vertices === undefined) { + return undefined; + } + const color = domainObject.getColorByColorType(style.colorType); + const linewidth = domainObject.isSelected ? style.selectedLineWidth : style.lineWidth; + const geometry = createBufferGeometry(vertices); + const material = new LineBasicMaterial({ + linewidth, + color, + depthTest: style.depthTest + }); + return new Line(geometry, material); + + function createBufferGeometry(vertices: number[]): BufferGeometry { + const verticesArray = new Float32Array(vertices); + const geometry = new BufferGeometry(); + geometry.setAttribute('position', new BufferAttribute(verticesArray, 3)); + return geometry; + } + } + private addLabels(): void { const { domainObject, style } = this; const { points } = domainObject; diff --git a/react-components/src/architecture/concrete/boxDomainObject/MeasurementTool.ts b/react-components/src/architecture/concrete/boxDomainObject/MeasurementTool.ts index 31b7455036a..efdbe2416a1 100644 --- a/react-components/src/architecture/concrete/boxDomainObject/MeasurementTool.ts +++ b/react-components/src/architecture/concrete/boxDomainObject/MeasurementTool.ts @@ -43,17 +43,17 @@ export class MeasurementTool extends BaseEditTool { return { key: 'MEASUREMENTS', fallback: 'Measurements' }; } - public override getToolbar(): Array | undefined { - const result = new Array(); - result.push(new SetMeasurmentTypeCommand(MeasureType.Line)); - result.push(new SetMeasurmentTypeCommand(MeasureType.Polyline)); - result.push(new SetMeasurmentTypeCommand(MeasureType.Polygon)); - result.push(new SetMeasurmentTypeCommand(MeasureType.HorizontalArea)); - result.push(new SetMeasurmentTypeCommand(MeasureType.VerticalArea)); - result.push(new SetMeasurmentTypeCommand(MeasureType.Volume)); - result.push(undefined); // Means separator - result.push(new ShowMeasurmentsOnTopCommand()); - return result; + public override getToolbar(): Array { + return [ + new SetMeasurmentTypeCommand(MeasureType.Line), + new SetMeasurmentTypeCommand(MeasureType.Polyline), + new SetMeasurmentTypeCommand(MeasureType.Polygon), + new SetMeasurmentTypeCommand(MeasureType.HorizontalArea), + new SetMeasurmentTypeCommand(MeasureType.VerticalArea), + new SetMeasurmentTypeCommand(MeasureType.Volume), + undefined, // Separator + new ShowMeasurmentsOnTopCommand() + ]; } public override getToolbarStyle(): PopupStyle { @@ -188,7 +188,6 @@ export class MeasurementTool extends BaseEditTool { if (measurment !== undefined) { this.deselectAll(measurment); measurment.setSelectedInteractive(true); - this.renderTarget.toolController.update(); return; } const ray = this.getRay(event); @@ -205,7 +204,6 @@ export class MeasurementTool extends BaseEditTool { rootDomainObject.addChildInteractive(domainObject); domainObject.setSelectedInteractive(true); domainObject.setVisibleInteractive(true, renderTarget); - this.renderTarget.toolController.update(); } } else { if (creator.addPoint(ray, intersection)) { diff --git a/react-components/src/architecture/concrete/config/StoryBookConfig.ts b/react-components/src/architecture/concrete/config/StoryBookConfig.ts new file mode 100644 index 00000000000..ba1accbc731 --- /dev/null +++ b/react-components/src/architecture/concrete/config/StoryBookConfig.ts @@ -0,0 +1,46 @@ +/*! + * Copyright 2024 Cognite AS + */ + +import { FlexibleControlsType } from '@cognite/reveal'; +import { type BaseCommand } from '../../base/commands/BaseCommand'; +import { PopupStyle } from '../../base/domainObjectsHelpers/PopupStyle'; +import { SetFlexibleControlsTypeCommand } from '../../base/concreteCommands/SetFlexibleControlsTypeCommand'; +import { SetTerrainVisibleCommand } from '../terrainDomainObject/SetTerrainVisibleCommand'; +import { UpdateTerrainCommand } from '../terrainDomainObject/UpdateTerrainCommand'; +import { FitViewCommand } from '../../base/concreteCommands/FitViewCommand'; +import { SetAxisVisibleCommand } from '../axis/SetAxisVisibleCommand'; +import { ExampleTool } from '../exampleDomainObject/ExampleTool'; +import { MeasurementTool } from '../boxDomainObject/MeasurementTool'; +import { AxisGizmoTool } from '@cognite/reveal/tools'; +import { BaseRevealConfig } from '../../base/renderTarget/BaseRevealConfig'; + +export class StoryBookConfig extends BaseRevealConfig { + // ================================================== + // OVERRIDES + // ================================================== + + public override createMainToolbar(): Array { + return [ + new SetFlexibleControlsTypeCommand(FlexibleControlsType.Orbit), + new SetFlexibleControlsTypeCommand(FlexibleControlsType.FirstPerson), + undefined, + new FitViewCommand(), + new SetAxisVisibleCommand(), + undefined, + new SetTerrainVisibleCommand(), + new UpdateTerrainCommand(), + undefined, + new ExampleTool(), + new MeasurementTool() + ]; + } + + public override createMainToolbarStyle(): PopupStyle { + return new PopupStyle({ right: 0, top: 0, horizontal: false }); + } + + public override createAxisGizmoTool(): AxisGizmoTool | undefined { + return new AxisGizmoTool(); + } +} diff --git a/react-components/src/architecture/concrete/exampleDomainObject/ExampleDomainObject.ts b/react-components/src/architecture/concrete/exampleDomainObject/ExampleDomainObject.ts new file mode 100644 index 00000000000..f8fc5313ce1 --- /dev/null +++ b/react-components/src/architecture/concrete/exampleDomainObject/ExampleDomainObject.ts @@ -0,0 +1,105 @@ +/*! + * Copyright 2024 Cognite AS + */ + +import { ExampleRenderStyle } from './ExampleRenderStyle'; +import { type RenderStyle } from '../../base/domainObjectsHelpers/RenderStyle'; +import { type ThreeView } from '../../base/views/ThreeView'; +import { ExampleView } from './ExampleView'; +import { NumberType, PanelInfo } from '../../base/domainObjectsHelpers/PanelInfo'; +import { + type CreateDraggerProps, + VisualDomainObject +} from '../../base/domainObjects/VisualDomainObject'; +import { Vector3 } from 'three'; +import { PopupStyle } from '../../base/domainObjectsHelpers/PopupStyle'; +import { DomainObjectPanelUpdater } from '../../base/reactUpdaters/DomainObjectPanelUpdater'; +import { type DomainObjectChange } from '../../base/domainObjectsHelpers/DomainObjectChange'; +import { Changes } from '../../base/domainObjectsHelpers/Changes'; +import { type BaseDragger } from '../../base/domainObjectsHelpers/BaseDragger'; +import { ExampleDragger } from './ExampleDragger'; + +export class ExampleDomainObject extends VisualDomainObject { + // ================================================== + // INSTANCE FIELDS + // ================================================== + + public readonly center = new Vector3(); + + // ================================================== + // INSTANCE PROPERTIES + // ================================================== + + public get renderStyle(): ExampleRenderStyle { + return super.getRenderStyle() as ExampleRenderStyle; + } + + // ================================================== + // OVERRIDES of DomainObject + // ================================================== + + public override get canBeRemoved(): boolean { + return true; + } + + public override get icon(): string { + return 'Circle'; + } + + public override get typeName(): string { + return 'Example'; + } + + public override createRenderStyle(): RenderStyle | undefined { + return new ExampleRenderStyle(); + } + + public override createDragger(props: CreateDraggerProps): BaseDragger | undefined { + return new ExampleDragger(props, this); + } + + public override getPanelInfo(): PanelInfo | undefined { + const info = new PanelInfo(); + info.setHeader('NAME', this.name); + add('XCORDINATE', 'X coordinate', this.center.x, NumberType.Length); + add('YCORDINATE', 'Y coordinate', this.center.y, NumberType.Length); + add('ZCORDINATE', 'Z coordinate', this.center.z, NumberType.Length); + return info; + + function add(key: string, fallback: string, value: number, numberType: NumberType): void { + info.add({ key, fallback, value, numberType }); + } + } + + public override getPanelInfoStyle(): PopupStyle { + // bottom = 66 because the toolbar is below + return new PopupStyle({ bottom: 66, left: 0 }); + } + + protected override notifyCore(change: DomainObjectChange): void { + super.notifyCore(change); + + if (!DomainObjectPanelUpdater.isActive) { + return; + } + if (this.isSelected) { + if (change.isChanged(Changes.deleted)) { + DomainObjectPanelUpdater.update(undefined); + } + if (change.isChanged(Changes.selected, Changes.geometry, Changes.naming)) { + DomainObjectPanelUpdater.update(this); + } + } else { + if (change.isChanged(Changes.selected)) { + DomainObjectPanelUpdater.update(undefined); // Deselected + } + } + } + // ================================================== + // OVERRIDES of VisualDomainObject + // ================================================== + + protected override createThreeView(): ThreeView | undefined { + return new ExampleView(); + } +} diff --git a/react-components/src/architecture/concrete/exampleDomainObject/ExampleDragger.ts b/react-components/src/architecture/concrete/exampleDomainObject/ExampleDragger.ts new file mode 100644 index 00000000000..5b472f34e96 --- /dev/null +++ b/react-components/src/architecture/concrete/exampleDomainObject/ExampleDragger.ts @@ -0,0 +1,49 @@ +/*! + * Copyright 2024 Cognite AS + */ + +import { type Ray, Vector3, Plane } from 'three'; +import { Changes } from '../../base/domainObjectsHelpers/Changes'; +import { type DomainObject } from '../../base/domainObjects/DomainObject'; +import { type ExampleDomainObject } from './ExampleDomainObject'; +import { BaseDragger } from '../../base/domainObjectsHelpers/BaseDragger'; +import { type CreateDraggerProps } from '../../base/domainObjects/VisualDomainObject'; + +export class ExampleDragger extends BaseDragger { + // ================================================== + // INSTANCE FIELDS + // ================================================== + + private readonly _domainObject: ExampleDomainObject; + private readonly _center: Vector3; + private readonly _plane: Plane; + + // ================================================== + // CONTRUCTOR + // ================================================== + + public constructor(props: CreateDraggerProps, domainObject: ExampleDomainObject) { + super(props); + this._domainObject = domainObject; + this._center = this._domainObject.center.clone(); + this._plane = new Plane().setFromNormalAndCoplanarPoint(this.ray.direction, this._center); + } + + // ================================================== + // OVERRIDES + // ================================================== + + public override get domainObject(): DomainObject { + return this._domainObject; + } + + public override onPointerDrag(_event: PointerEvent, ray: Ray): boolean { + const planeIntersect = ray.intersectPlane(this._plane, new Vector3()); + if (planeIntersect === null) { + return false; + } + this._domainObject.center.copy(planeIntersect); + this.domainObject.notify(Changes.geometry); + return true; + } +} diff --git a/react-components/src/architecture/concrete/exampleDomainObject/ExampleRenderStyle.ts b/react-components/src/architecture/concrete/exampleDomainObject/ExampleRenderStyle.ts new file mode 100644 index 00000000000..27711a8a4aa --- /dev/null +++ b/react-components/src/architecture/concrete/exampleDomainObject/ExampleRenderStyle.ts @@ -0,0 +1,23 @@ +/*! + * Copyright 2024 Cognite AS + */ + +import { cloneDeep } from 'lodash'; +import { RenderStyle } from '../../base/domainObjectsHelpers/RenderStyle'; + +export class ExampleRenderStyle extends RenderStyle { + // ================================================== + // INSTANCE FIELDS + // ================================================== + + public radius = 1; + public opacity = 0.5; + + // ================================================== + // OVERRIDES of BaseStyle + // ================================================== + + public override clone(): RenderStyle { + return cloneDeep(this); + } +} diff --git a/react-components/src/architecture/concrete/exampleDomainObject/ExampleTool.ts b/react-components/src/architecture/concrete/exampleDomainObject/ExampleTool.ts new file mode 100644 index 00000000000..52c030902a8 --- /dev/null +++ b/react-components/src/architecture/concrete/exampleDomainObject/ExampleTool.ts @@ -0,0 +1,133 @@ +/*! + * Copyright 2024 Cognite AS + */ + +import { ExampleDomainObject } from './ExampleDomainObject'; +import { CDF_TO_VIEWER_TRANSFORMATION, type AnyIntersection } from '@cognite/reveal'; +import { type BaseCommand, type Tooltip } from '../../base/commands/BaseCommand'; +import { isDomainObjectIntersection } from '../../base/domainObjectsHelpers/DomainObjectIntersection'; +import { BaseEditTool } from '../../base/commands/BaseEditTool'; +import { Changes } from '../../base/domainObjectsHelpers/Changes'; +import { ResetAllExamplesCommand } from './commands/ResetAllExamplesCommand'; +import { DeleteAllExamplesCommand } from './commands/DeleteAllExamplesCommand'; +import { ShowAllExamplesCommand } from './commands/ShowAllExamplesCommand'; +import { clamp } from 'lodash'; +export class ExampleTool extends BaseEditTool { + // ================================================== + // OVERRIDES of BaseCommand + // ================================================== + + public override get icon(): string { + return 'Circle'; + } + + public override get tooltip(): Tooltip { + return { key: 'EXAMPLE_EDIT', fallback: 'Create or edit a point' }; + } + + // ================================================== + // OVERRIDES of BaseTool + // ================================================== + + public override onDeactivate(): void { + super.onDeactivate(); + this.deselectAll(); + } + + public override onKey(event: KeyboardEvent, down: boolean): void { + if (down && event.key === 'Delete') { + const domainObject = this.rootDomainObject.getSelectedDescendantByType(ExampleDomainObject); + if (domainObject !== undefined) { + domainObject.removeInteractive(); + } + return; + } + super.onKey(event, down); + } + + public override async onWheel(event: WheelEvent): Promise { + const intersection = await this.getIntersection(event); + const domainObject = this.getExampleDomainObject(intersection); + if (domainObject === undefined || !domainObject.isSelected) { + await super.onWheel(event); + return; + } + if (event.ctrlKey) { + const delta = Math.sign(event.deltaY) * 0.05; + domainObject.renderStyle.opacity = clamp(domainObject.renderStyle.opacity + delta, 0.2, 1); + domainObject.notify(Changes.renderStyle); + } else { + // Change radius + const factor = 1 - Math.sign(event.deltaY) * 0.1; + domainObject.renderStyle.radius *= factor; + } + domainObject.notify(Changes.renderStyle); + } + + public override async onHover(event: PointerEvent): Promise { + const intersection = await this.getIntersection(event); + const domainObject = this.getExampleDomainObject(intersection); + + if (domainObject instanceof ExampleDomainObject) { + this.renderTarget.setMoveCursor(); + } else if (intersection !== undefined) { + this.renderTarget.setCrosshairCursor(); + } else { + this.renderTarget.setNavigateCursor(); + } + } + + public override async onClick(event: PointerEvent): Promise { + const { renderTarget, rootDomainObject } = this; + + const intersection = await this.getIntersection(event); + if (intersection === undefined) { + await super.onClick(event); + return; + } + { + const domainObject = this.getExampleDomainObject(intersection); + if (domainObject !== undefined) { + this.deselectAll(domainObject); + domainObject.setSelectedInteractive(true); + return; + } + } + const center = intersection.point.clone(); + const matrix = CDF_TO_VIEWER_TRANSFORMATION.clone().invert(); + center.applyMatrix4(matrix); + + const domainObject = new ExampleDomainObject(); + domainObject.center.copy(center); + + this.deselectAll(); + rootDomainObject.addChildInteractive(domainObject); + domainObject.setVisibleInteractive(true, renderTarget); + domainObject.setSelectedInteractive(true); + } + + public override getToolbar(): Array { + return [ + new ResetAllExamplesCommand(), + new ShowAllExamplesCommand(), + new DeleteAllExamplesCommand() + ]; + } + + // ================================================== + // INSTANCE METHODS + // ================================================== + + private getExampleDomainObject( + intersection: AnyIntersection | undefined + ): ExampleDomainObject | undefined { + if (!isDomainObjectIntersection(intersection)) { + return undefined; + } + if (intersection.domainObject instanceof ExampleDomainObject) { + return intersection.domainObject; + } else { + return undefined; + } + } +} diff --git a/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts b/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts new file mode 100644 index 00000000000..eac264506ea --- /dev/null +++ b/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts @@ -0,0 +1,111 @@ +/*! + * Copyright 2024 Cognite AS + */ + +import { Mesh, MeshPhongMaterial, Sphere, SphereGeometry, Vector3 } from 'three'; +import { type ExampleDomainObject } from './ExampleDomainObject'; +import { type DomainObjectChange } from '../../base/domainObjectsHelpers/DomainObjectChange'; +import { Changes } from '../../base/domainObjectsHelpers/Changes'; +import { type ExampleRenderStyle } from './ExampleRenderStyle'; +import { GroupThreeView } from '../../base/views/GroupThreeView'; +import { + CDF_TO_VIEWER_TRANSFORMATION, + type CustomObjectIntersectInput, + type CustomObjectIntersection +} from '@cognite/reveal'; +import { type DomainObjectIntersection } from '../../base/domainObjectsHelpers/DomainObjectIntersection'; +import { WHITE_COLOR } from '../../base/utilities/colors/colorExtensions'; + +export class ExampleView extends GroupThreeView { + // ================================================== + // INSTANCE PROPERTIES + // ================================================== + + protected override get domainObject(): ExampleDomainObject { + return super.domainObject as ExampleDomainObject; + } + + protected override get style(): ExampleRenderStyle { + return super.style as ExampleRenderStyle; + } + + // ================================================== + // OVERRIDES of BaseView + // ================================================== + + public override update(change: DomainObjectChange): void { + super.update(change); + if (this.isEmpty) { + return; + } + if ( + change.isChanged(Changes.geometry) || + change.isChanged(Changes.selected) || + change.isChanged(Changes.renderStyle) || + change.isChanged(Changes.color) + ) { + this.removeChildren(); + this.invalidateBoundingBox(); + this.invalidateRenderTarget(); + } + } + + // ================================================== + // OVERRIDES of GroupThreeView + // ================================================== + + protected override addChildren(): void { + const { domainObject, style } = this; + + const color = domainObject.color; + const geometry = new SphereGeometry(style.radius, 32, 16); + const material = new MeshPhongMaterial({ + color, + emissive: WHITE_COLOR, + emissiveIntensity: domainObject.isSelected ? 0.4 : 0.0, + shininess: 5, + opacity: style.opacity, + transparent: true + }); + const sphere = new Mesh(geometry, material); + const center = domainObject.center.clone(); + center.applyMatrix4(CDF_TO_VIEWER_TRANSFORMATION); + sphere.position.copy(center); + this.addChild(sphere); + } + + // Do actually not need this because the base class takes care of this + public override intersectIfCloser( + intersectInput: CustomObjectIntersectInput, + closestDistance: number | undefined + ): undefined | CustomObjectIntersection { + const { domainObject, style } = this; + + const ray = intersectInput.raycaster.ray; + const center = domainObject.center.clone(); + center.applyMatrix4(CDF_TO_VIEWER_TRANSFORMATION); + const sphere = new Sphere(center, style.radius); + const point = ray.intersectSphere(sphere, new Vector3()); + if (point === null) { + return undefined; + } + const distanceToCamera = point.distanceTo(ray.origin); + if (closestDistance !== undefined && closestDistance < distanceToCamera) { + return undefined; + } + if (!intersectInput.isVisible(point)) { + return undefined; + } + const customObjectIntersection: DomainObjectIntersection = { + type: 'customObject', + point, + distanceToCamera, + customObject: this, + domainObject + }; + if (this.shouldPickBoundingBox) { + customObjectIntersection.boundingBox = this.boundingBox; + } + return customObjectIntersection; + } +} diff --git a/react-components/src/architecture/concrete/exampleDomainObject/commands/DeleteAllExamplesCommand.ts b/react-components/src/architecture/concrete/exampleDomainObject/commands/DeleteAllExamplesCommand.ts new file mode 100644 index 00000000000..e6729404595 --- /dev/null +++ b/react-components/src/architecture/concrete/exampleDomainObject/commands/DeleteAllExamplesCommand.ts @@ -0,0 +1,40 @@ +/*! + * Copyright 2024 Cognite AS + * BaseTool: Base class for the tool are used to interact with the render target. + */ + +import { RenderTargetCommand } from '../../../base/commands/RenderTargetCommand'; +import { type Tooltip } from '../../../base/commands/BaseCommand'; +import { ExampleDomainObject } from '../ExampleDomainObject'; + +export class DeleteAllExamplesCommand extends RenderTargetCommand { + // ================================================== + // OVERRIDES + // ================================================== + + public override get tooltip(): Tooltip { + return { key: 'EXAMPLES_DELETE', fallback: 'Remove all examples' }; + } + + public override get icon(): string { + return 'Delete'; + } + + public override get isEnabled(): boolean { + const first = this.getFirst(); + return first !== undefined && first.canBeRemoved; + } + + protected override invokeCore(): boolean { + const array = Array.from(this.rootDomainObject.getDescendantsByType(ExampleDomainObject)); + array.reverse(); + for (const domainObject of array) { + domainObject.removeInteractive(); + } + return true; + } + + private getFirst(): ExampleDomainObject | undefined { + return this.rootDomainObject.getDescendantByType(ExampleDomainObject); + } +} diff --git a/react-components/src/architecture/concrete/exampleDomainObject/commands/ResetAllExamplesCommand.ts b/react-components/src/architecture/concrete/exampleDomainObject/commands/ResetAllExamplesCommand.ts new file mode 100644 index 00000000000..0ff53c31d66 --- /dev/null +++ b/react-components/src/architecture/concrete/exampleDomainObject/commands/ResetAllExamplesCommand.ts @@ -0,0 +1,39 @@ +/*! + * Copyright 2024 Cognite AS + * BaseTool: Base class for the tool are used to interact with the render target. + */ + +import { RenderTargetCommand } from '../../../base/commands/RenderTargetCommand'; +import { type Tooltip } from '../../../base/commands/BaseCommand'; +import { ExampleDomainObject } from '../ExampleDomainObject'; +import { Changes } from '../../../base/domainObjectsHelpers/Changes'; + +export class ResetAllExamplesCommand extends RenderTargetCommand { + // ================================================== + // OVERRIDES + // ================================================== + + public override get tooltip(): Tooltip { + return { key: 'EXAMPLES_RESET', fallback: 'Reset' }; + } + + public override get icon(): string { + return 'Copy'; + } + + public override get isEnabled(): boolean { + return this.getFirst() !== undefined; + } + + protected override invokeCore(): boolean { + for (const domainObject of this.rootDomainObject.getDescendantsByType(ExampleDomainObject)) { + domainObject.setRenderStyle(undefined); + domainObject.notify(Changes.renderStyle); + } + return true; + } + + private getFirst(): ExampleDomainObject | undefined { + return this.rootDomainObject.getDescendantByType(ExampleDomainObject); + } +} diff --git a/react-components/src/architecture/concrete/exampleDomainObject/commands/ShowAllExamplesCommand.ts b/react-components/src/architecture/concrete/exampleDomainObject/commands/ShowAllExamplesCommand.ts new file mode 100644 index 00000000000..fdf4b34616d --- /dev/null +++ b/react-components/src/architecture/concrete/exampleDomainObject/commands/ShowAllExamplesCommand.ts @@ -0,0 +1,50 @@ +/*! + * Copyright 2024 Cognite AS + * BaseTool: Base class for the tool are used to interact with the render target. + */ + +import { RenderTargetCommand } from '../../../base/commands/RenderTargetCommand'; +import { type Tooltip } from '../../../base/commands/BaseCommand'; +import { ExampleDomainObject } from '../ExampleDomainObject'; + +export class ShowAllExamplesCommand extends RenderTargetCommand { + // ================================================== + // OVERRIDES + // ================================================== + + public override get tooltip(): Tooltip { + return { key: 'EXAMPLES_SHOW', fallback: 'Show all examples' }; + } + + public override get icon(): string { + return 'EyeShow'; + } + + public override get isEnabled(): boolean { + return this.getFirst() !== undefined; + } + + public override get isCheckable(): boolean { + return true; + } + + public override get isChecked(): boolean { + const domainObject = this.getFirst(); + if (domainObject === undefined) { + return false; + } + return domainObject.isVisible(this.renderTarget); + } + + protected override invokeCore(): boolean { + const isVisible = this.isChecked; + for (const domainObject of this.rootDomainObject.getDescendantsByType(ExampleDomainObject)) { + domainObject.setVisibleInteractive(!isVisible, this.renderTarget); + } + return true; + } + + private getFirst(): ExampleDomainObject | undefined { + return this.rootDomainObject.getDescendantByType(ExampleDomainObject); + } +} diff --git a/react-components/src/components/Architecture/DomainObjectPanel.tsx b/react-components/src/components/Architecture/DomainObjectPanel.tsx index e4a0758d9b8..392d1619dc7 100644 --- a/react-components/src/components/Architecture/DomainObjectPanel.tsx +++ b/react-components/src/components/Architecture/DomainObjectPanel.tsx @@ -57,21 +57,21 @@ export const DomainObjectPanel = (): ReactElement => { {t(header.key, header.fallback)} )} - - - - - + }}> + + + + + )} CreateButton(new FitViewCommand()); static NavigationTool = (): ReactElement => CreateButton(new NavigationTool()); static SetAxisVisible = (): ReactElement => CreateButton(new SetAxisVisibleCommand()); - static SetTerrainVisible = (): ReactElement => CreateButton(new SetTerrainVisibleCommand()); - static UpdateTerrain = (): ReactElement => CreateButton(new UpdateTerrainCommand()); static Measurement = (): ReactElement => CreateButton(new MeasurementTool()); static SetFlexibleControlsTypeOrbit = (): ReactElement => diff --git a/react-components/src/components/Architecture/ActiveToolToolbar.tsx b/react-components/src/components/Architecture/Toolbar.tsx similarity index 59% rename from react-components/src/components/Architecture/ActiveToolToolbar.tsx rename to react-components/src/components/Architecture/Toolbar.tsx index 954ae760eef..fdce7c5a538 100644 --- a/react-components/src/components/Architecture/ActiveToolToolbar.tsx +++ b/react-components/src/components/Architecture/Toolbar.tsx @@ -9,8 +9,27 @@ import { CommandButton } from './CommandButton'; import { type BaseCommand } from '../../architecture/base/commands/BaseCommand'; import { useRenderTarget } from '../RevealCanvas/ViewerContext'; import { ActiveToolUpdater } from '../../architecture/base/reactUpdaters/ActiveToolUpdater'; +import { type PopupStyle } from '../../architecture/base/domainObjectsHelpers/PopupStyle'; + +export const MainToolbar = (): ReactElement => { + const renderTarget = useRenderTarget(); + if (renderTarget === undefined) { + return <>; + } + const config = renderTarget.config; + if (config === undefined) { + return <>; + } + const commands = config.createMainToolbar(); + if (commands.length === 0) { + return <>; + } + const style = config.createMainToolbarStyle(); + return CreateToolToolbar(commands, style); +}; export const ActiveToolToolbar = (): ReactElement => { + // const [_activeToolUpdater, setActiveToolUpdater] = useState(0); ActiveToolUpdater.setCounterDelegate(setActiveToolUpdater); @@ -23,10 +42,21 @@ export const ActiveToolToolbar = (): ReactElement => { return <>; } const commands = activeTool.getToolbar(); - if (commands === undefined || commands.length === 0) { + if (commands.length === 0) { return <>; } const style = activeTool.getToolbarStyle(); + return CreateToolToolbar(commands, style); +}; + +const CreateToolToolbar = ( + commands: Array, + style: PopupStyle +): ReactElement => { + // + if (commands.length === 0 || style === null) { + return <>; + } return ( { margin: style.marginPx // Padding is not used here }}> - - <>{commands.map((command, index): ReactElement => addCommand(command, index))} + + <>{commands.map((command, index): ReactElement => addCommand(command, style, index))} ); }; -function addCommand(command: BaseCommand | undefined, index: number): ReactElement { +function addCommand( + command: BaseCommand | undefined, + style: PopupStyle, + index: number +): ReactElement { if (command === undefined) { - return ; + const direction = style.isDividerHorizontal ? 'horizontal' : 'vertical'; + return ; } return ; } @@ -57,6 +96,4 @@ const Container = styled.div` display: block; `; -const MyCustomToolbar = styled(withSuppressRevealEvents(ToolBar))` - flex-direction: row; -`; +const MyCustomToolbar = styled(withSuppressRevealEvents(ToolBar))``; diff --git a/react-components/src/index.ts b/react-components/src/index.ts index 9d8b7646a0c..cb06b695db7 100644 --- a/react-components/src/index.ts +++ b/react-components/src/index.ts @@ -148,7 +148,7 @@ export type { CriteriaTypes } from './components/RuleBasedOutputs/types'; -export { ActiveToolToolbar } from './components/Architecture/ActiveToolToolbar'; +export { ActiveToolToolbar } from './components/Architecture/Toolbar'; export { DomainObjectPanel } from './components/Architecture/DomainObjectPanel'; export { RevealButtons } from './components/Architecture/ToolButtons'; diff --git a/react-components/stories/Architecture.stories.tsx b/react-components/stories/Architecture.stories.tsx index f2489fe5239..524f3b59f73 100644 --- a/react-components/stories/Architecture.stories.tsx +++ b/react-components/stories/Architecture.stories.tsx @@ -7,21 +7,17 @@ import { CadModelContainer, type QualitySettings, RevealToolbar, - withSuppressRevealEvents, - withCameraStateUrlParam, useGetCameraStateFromUrlParam, useCameraNavigation } from '../src'; import { Color } from 'three'; -import styled from 'styled-components'; -import { Button, Menu, ToolBar } from '@cognite/cogs.js'; +import { Button, Menu } from '@cognite/cogs.js'; import { type ReactElement, useState, useEffect } from 'react'; import { signalStoryReadyForScreenshot } from './utilities/signalStoryReadyForScreenshot'; import { RevealStoryContainer } from './utilities/RevealStoryContainer'; import { getAddModelOptionsFromUrl } from './utilities/getAddModelOptionsFromUrl'; -import { RevealButtons } from '../src/components/Architecture/ToolButtons'; import { DomainObjectPanel } from '../src/components/Architecture/DomainObjectPanel'; -import { ActiveToolToolbar } from '../src/components/Architecture/ActiveToolToolbar'; +import { ActiveToolToolbar, MainToolbar } from '../src/components/Architecture/Toolbar'; const meta = { title: 'Example/Architecture', @@ -32,12 +28,6 @@ const meta = { export default meta; type Story = StoryObj; -const MyCustomToolbar = styled(withSuppressRevealEvents(withCameraStateUrlParam(ToolBar)))` - position: absolute; - right: 20px; - top: 70px; -`; - const exampleCustomSettingElements = (): ReactElement => { const [originalCadColor, setOriginalCadColor] = useState(false); @@ -100,26 +90,9 @@ export const Main: Story = { lowFidelitySettings={exampleLowQualitySettings} highFidelitySettings={exampleHighQualitySettings} /> - - <> - - - - <> - - - - <> - - - - <> - - - - - + + ); } diff --git a/react-components/stories/utilities/RevealStoryContainer.tsx b/react-components/stories/utilities/RevealStoryContainer.tsx index 2c6bff06d0e..d232733b117 100644 --- a/react-components/stories/utilities/RevealStoryContainer.tsx +++ b/react-components/stories/utilities/RevealStoryContainer.tsx @@ -17,6 +17,7 @@ import { import { type Image360AnnotationCache } from '../../src/components/CacheProvider/Image360AnnotationCache'; import { type SceneIdentifiers } from '../../src/components/SceneContainer/sceneTypes'; import { RevealRenderTarget } from '../../src/architecture/base/renderTarget/RevealRenderTarget'; +import { StoryBookConfig } from '../../src/architecture/concrete/config/StoryBookConfig'; type RevealStoryContainerProps = Omit & { sdk?: CogniteClient; @@ -51,7 +52,7 @@ export const RevealStoryContext = ({ useFlexibleCameraManager: true }); const renderTarget = new RevealRenderTarget(newViewer); - renderTarget.addAxisGizmo(); + renderTarget.setConfig(new StoryBookConfig()); return renderTarget; } }, [viewer]);