Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat) react-component: Working on example code and the course #4575

Merged
merged 10 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { clear, remove } from '../utilities/extensions/arrayExtensions';
type UpdateDelegate = (command: BaseCommand) => void;

/**
* Base class for all command and tools. Thses are object that can do a
* Base class for all command and tools. These are object that can do a
* user interaction with the system. It also have enough information to
* generate the UI for the command.
*/
Expand Down Expand Up @@ -55,6 +55,10 @@ export abstract class BaseCommand {
return 'Unknown';
}

public get buttonType(): string {
return 'ghost';
}

public get isEnabled(): boolean {
return true;
}
Expand Down
70 changes: 58 additions & 12 deletions react-components/src/architecture/base/commands/BaseEditTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/

import { NavigationTool } from './NavigationTool';
import { type DomainObject } from '../domainObjects/DomainObject';
import { isDomainObjectIntersection } from '../domainObjectsHelpers/DomainObjectIntersection';
import { type BaseDragger } from '../domainObjectsHelpers/BaseDragger';
import { VisualDomainObject } from '../domainObjects/VisualDomainObject';
Expand All @@ -13,7 +12,7 @@ import { type AnyIntersection, CDF_TO_VIEWER_TRANSFORMATION } from '@cognite/rev
* The `BaseEditTool` class is an abstract class that extends the `NavigationTool` class.
* It provides a base implementation for editing tools in a specific architecture.
* Custom editing tools can be created by extending this class and overriding its methods.
* This class will also proivide the dragging functionality if the picked domain object has
* This class will also provide the dragging functionality if the picked domain object has
* createDragger() overridden.
*/
export abstract class BaseEditTool extends NavigationTool {
Expand Down Expand Up @@ -76,18 +75,17 @@ export abstract class BaseEditTool extends NavigationTool {

/**
* Determines whether the specified domain object can be selected or dragged by this edit tool.
*
* @param _domainObject - The domain object to be accepted.
* Override this function of the selection mechanism should be used.
* @param domainObject - The domain object to be accepted.
* @returns `true` if the domain object can be accepted, `false` otherwise.
*/
protected canBeSelected(_domainObject: DomainObject): boolean {
protected canBeSelected(_domainObject: VisualDomainObject): boolean {
return false;
}

/**
* Override this function to create custom dragger
* with other creation logic. Otherwise createDragger in
* the DomainObject itself
* with other creation logic.
*/
protected async createDragger(event: PointerEvent): Promise<BaseDragger | undefined> {
const intersection = await this.getIntersection(event);
Expand All @@ -113,9 +111,14 @@ export abstract class BaseEditTool extends NavigationTool {
// INSTANCE METHODS
// ==================================================

/**
* Deselects all visual domain objects except for the specified object.
* If no object is specified, all visual domain objects will be deselected.
* @param except - The visual domain object to exclude from deselection.
*/
protected deselectAll(except?: VisualDomainObject | undefined): void {
const { rootDomainObject } = this;
for (const domainObject of rootDomainObject.getDescendants()) {
for (const domainObject of rootDomainObject.getDescendantsByType(VisualDomainObject)) {
if (!this.canBeSelected(domainObject)) {
continue;
}
Expand All @@ -126,18 +129,61 @@ export abstract class BaseEditTool extends NavigationTool {
}
}

/**
* Retrieves all selected domain objects.
* Use only if multi selection is expected.
* @returns A generator that yields each selected domain object.
*/
protected *getAllSelected(): Generator<VisualDomainObject> {
const { rootDomainObject } = this;
for (const domainObject of rootDomainObject.getDescendantsByType(VisualDomainObject)) {
if (!domainObject.isSelected) {
continue;
}
if (!this.canBeSelected(domainObject)) {
continue;
}
yield domainObject;
}
}

/**
* Retrieves the selected VisualDomainObject.
* Use only if single selection is expected.
* @returns The selected DomainObject, or undefined if no object is selected.
*/
protected getSelected(): VisualDomainObject | undefined {
const { rootDomainObject } = this;
for (const domainObject of rootDomainObject.getDescendantsByType(VisualDomainObject)) {
if (!domainObject.isSelected) {
continue;
}
if (!this.canBeSelected(domainObject)) {
continue;
}
return domainObject;
}
return undefined;
}

/**
* Retrieves the intersected visual domain object from the given intersection.
* @param intersection - The intersection to retrieve the domain object from.
* @returns The intersected visual domain object, or undefined if no valid domain object is found.
*/
protected getIntersectedDomainObject(
intersection: AnyIntersection | undefined
): VisualDomainObject | undefined {
if (!isDomainObjectIntersection(intersection)) {
return undefined;
}
if (!this.canBeSelected(intersection.domainObject)) {
const { domainObject } = intersection;
if (!(domainObject instanceof VisualDomainObject)) {
return undefined;
} else if (intersection.domainObject instanceof VisualDomainObject) {
return intersection.domainObject;
} else {
}
if (!this.canBeSelected(domainObject)) {
return undefined;
}
return domainObject;
}
}
5 changes: 2 additions & 3 deletions react-components/src/architecture/base/commands/BaseTool.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*!
* Copyright 2024 Cognite AS
* BaseTool: Base class for the tool are used to interact with the render target.
*/

import { type Ray, Raycaster, type Vector2 } from 'three';
Expand All @@ -24,7 +23,7 @@ import { PopupStyle } from '../domainObjectsHelpers/PopupStyle';
import { ThreeView } from '../views/ThreeView';

/**
* Base class for intraction in the 3D viewer
* Base class for interactions in the 3D viewer
* Provides common functionality and virtual methods to be overridden by derived classes.
*/
export abstract class BaseTool extends RenderTargetCommand {
Expand Down Expand Up @@ -58,7 +57,7 @@ export abstract class BaseTool extends RenderTargetCommand {
}

public getToolbarStyle(): PopupStyle {
// Override this to pclase the extra separate toolbar
// Override this to place the the toolbar
// Default lower left corner
return new PopupStyle({ bottom: 0, left: 0 });
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*!
* Copyright 2024 Cognite AS
* BaseTool: Base class for the tool are used to interact with the render target.
*/

import { BaseTool } from './BaseTool';
Expand All @@ -13,7 +12,7 @@ import { type TranslateKey } from '../utilities/TranslateKey';
*/
export class NavigationTool extends BaseTool {
// ==================================================
// INSTANVE PROPERTIES
// INSTANCE PROPERTIES
// ==================================================

private get cameraManager(): IFlexibleCameraManager {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*!
* Copyright 2024 Cognite AS
* BaseTool: Base class for the tool are used to interact with the render target.
*/

import { BaseCommand } from '../commands/BaseCommand';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*!
* Copyright 2024 Cognite AS
* BaseTool: Base class for the tool are used to interact with the render target.
*/

import { BaseCommand } from '../commands/BaseCommand';
Expand All @@ -25,6 +24,10 @@ export class DeleteDomainObjectCommand extends BaseCommand {
return 'Delete';
}

public override get buttonType(): string {
return 'ghost-destructive';
}

public override get isEnabled(): boolean {
return this._domainObject !== undefined && this._domainObject.canBeRemoved;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
/*!
* Copyright 2024 Cognite AS
* BaseTool: Base class for the tool are used to interact with the render target.
*/

import { RenderTargetCommand } from '../commands/RenderTargetCommand';
import { Changes } from '../domainObjectsHelpers/Changes';
import { type TranslateKey } from '../utilities/TranslateKey';

export class ToogleMetricUnitsCommand extends RenderTargetCommand {
export class ToggleMetricUnitsCommand extends RenderTargetCommand {
// ==================================================
// OVERRIDES of BaseCommand
// ==================================================
Expand All @@ -21,15 +20,13 @@ export class ToogleMetricUnitsCommand extends RenderTargetCommand {
}

public override get isChecked(): boolean {
const { renderTarget } = this;
return renderTarget.rootDomainObject.unitSystem.isMetric;
return this.rootDomainObject.unitSystem.isMetric;
}

protected override invokeCore(): boolean {
const { renderTarget } = this;
const unitSystem = renderTarget.rootDomainObject.unitSystem;
const unitSystem = this.rootDomainObject.unitSystem;
unitSystem.isMetric = !unitSystem.isMetric;
renderTarget.rootDomainObject.notifyRecursive(Changes.unit);
this.rootDomainObject.notifyDescendants(Changes.unit);
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import { type Color } from 'three';
import { BLACK_COLOR, WHITE_COLOR } from '../utilities/colors/colorExtensions';
import { type RenderStyle } from '../domainObjectsHelpers/RenderStyle';
import { DomainObjectChange } from '../domainObjectsHelpers/DomainObjectChange';
import { Changes } from '../domainObjectsHelpers/Changes';
Expand All @@ -13,7 +14,6 @@ import { clear, removeAt } from '../utilities/extensions/arrayExtensions';
import { getNextColor } from '../utilities/colors/getNextColor';
import { type RevealRenderTarget } from '../renderTarget/RevealRenderTarget';
import { ColorType } from '../domainObjectsHelpers/ColorType';
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';
Expand Down Expand Up @@ -42,7 +42,7 @@ export abstract class DomainObject {
// For instance you can have many crop boxes, but only one can be used at the time.
private _isActive: boolean = false;

// Expaned when it is shown in a tree view
// Expand when it is shown in a tree view
private _isExpanded = false;

// Parent-Child relationship
Expand Down Expand Up @@ -74,7 +74,7 @@ export abstract class DomainObject {
}

// ==================================================
// INSTANCE/VIRTUAL METHODS: Nameing
// INSTANCE/VIRTUAL METHODS: Naming
// ==================================================

public get canChangeName(): boolean {
Expand Down Expand Up @@ -246,6 +246,15 @@ export abstract class DomainObject {
protected notifyCore(change: DomainObjectChange): void {
this.views.notify(this, change);

// If isRenderStyleRoot is true, notify all descendants
if (change.isChanged(Changes.renderStyle) && this.isRenderStyleRoot) {
const description = change.getChangedDescription(Changes.renderStyle);
if (description !== undefined) {
const renderStyleChange = new DomainObjectChange(description);
this.notifyDescendants(renderStyleChange);
}
}

if (
change.isChanged(
Changes.visibleState,
Expand Down Expand Up @@ -309,13 +318,21 @@ export abstract class DomainObject {

/**
* Override if the render style is taken from another domain object, for instance the parent
* or somewhere else in the hieracy
* or somewhere else in the hierarchy
* @returns The render style root
*/
public get renderStyleRoot(): DomainObject | undefined {
return undefined;
}

/**
* Override if this domain object is a render style root, se method above
* @returns true if this is a render style root
*/
public get isRenderStyleRoot(): boolean {
return false;
}

/**
* Factory method to create the render style for the domain object.
* Override this method to create a custom render style.
Expand All @@ -328,7 +345,7 @@ export abstract class DomainObject {
/**
* Verifies the render style for the domain object, because the render style may
* be not valid in some cases. In this method you can change the render style.
* You can also change som fields in the rebnderstyle to get default values
* You can also change som fields in the renderStyle to get default values
* dependent of the domain object itself.
* Override this method when needed
*/
Expand Down Expand Up @@ -378,7 +395,7 @@ export abstract class DomainObject {
public setVisibleInteractive(
visible: boolean,
renderTarget: RevealRenderTarget,
topLevel = true // When calling this from outside, this value should alwaus be true
topLevel = true // When calling this from outside, this value should always be true
): boolean {
const visibleState = this.getVisibleState(renderTarget);
if (visibleState === VisibleState.Disabled) {
Expand Down Expand Up @@ -413,7 +430,7 @@ export abstract class DomainObject {
this.notifyCore(change);
}

public notifyRecursive(change: DomainObjectChange | symbol): void {
public notifyDescendants(change: DomainObjectChange | symbol): void {
if (!(change instanceof DomainObjectChange)) {
change = new DomainObjectChange(change);
}
Expand Down Expand Up @@ -464,7 +481,7 @@ export abstract class DomainObject {
}

public get root(): DomainObject {
// Returns the root of the hierarcy, regardless what it is
// Returns the root of the hierarchy, regardless what it is
return this.parent === undefined ? this : this.parent.root;
}

Expand Down Expand Up @@ -776,7 +793,7 @@ export abstract class DomainObject {

// ==================================================
// INSTANCE METHODS: Color type
// Used in the renderstyle to determin which of the color a domain object should have.
// Used in the render style to determine which of the color a domain object should have.
// ==================================================

public supportsColorType(colorType: ColorType, solid: boolean): boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export abstract class VisualDomainObject extends DomainObject {

/**
* Determines whether the visual domain object can create a three view.
* It may have a state when it can not create a view bacause of other dependencies
* It may have a state when it can not create a view because of other dependencies
*
* @returns A boolean value indicating whether the visual domain object can create a three view.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ export abstract class BaseCreator {
// ==================================================

/**
* Gets the value indicating whether to prefer intersection with somthing.
* Gets the value indicating whether to prefer intersection with something.
* If this is true, it will first try to intersect an object. If false the point
* will normally be calculatd based on the previous point and the ray in addPointCore
* will normally be calculated based on the previous point and the ray in addPointCore
*
* @returns {boolean} The value indicating whether to prefer intersection.
*/
Expand All @@ -73,7 +73,7 @@ export abstract class BaseCreator {
protected abstract get minimumPointCount(): number;

/**
* @returns The maximim required points to create the domain object.
* @returns The maximum required points to create the domain object.
*/

protected abstract get maximumPointCount(): number;
Expand Down
Loading
Loading