diff --git a/canvas_editor/editor/templates/editor/editor.html b/canvas_editor/editor/templates/editor/editor.html index fc2bda92..2caae1a0 100644 --- a/canvas_editor/editor/templates/editor/editor.html +++ b/canvas_editor/editor/templates/editor/editor.html @@ -46,7 +46,7 @@ "modeSelector": "{% static 'js/editor/modeSelector.mjs' %}", "message_dict": "{% static 'js/message_dict.js' %}", "path_dict": "{% static 'js/path_dict.js' %}", - "projectOverviewManager": "{% static 'js/projectOverviewManager.mjs' %}" + "movableCanvasObjects": "{% static 'js/editor/objects/movableCanvasObjects.mjs' %}" } } diff --git a/canvas_editor/jsconfig.json b/canvas_editor/jsconfig.json index 496becbb..f46f23e7 100644 --- a/canvas_editor/jsconfig.json +++ b/canvas_editor/jsconfig.json @@ -37,7 +37,7 @@ "modeSelector": ["static/js/editor/modeSelector.mjs"], "message_dict": ["static/js/message_dict.js"], "path_dict": ["static/js/path_dict.js"], - "projectOverviewManager": ["static/js/projectOverviewManager.mjs"] + "movableCanvasObjects": ["static/js/editor/objects/movableCanvasObjects.mjs"] } } } diff --git a/canvas_editor/static/js/editor/objects/canvasObject.mjs b/canvas_editor/static/js/editor/objects/canvasObject.mjs index 533e477b..3097daaa 100644 --- a/canvas_editor/static/js/editor/objects/canvasObject.mjs +++ b/canvas_editor/static/js/editor/objects/canvasObject.mjs @@ -1,41 +1,62 @@ -import { InspectorComponent } from "inspectorComponents"; +import { HeaderInspectorComponent, InspectorComponent } from "inspectorComponents"; import { Object3D, Vector3 } from "three"; import * as THREE from "three"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; -import { methodMustBeImplementedError } from "message_dict"; +import { + methodMustBeImplementedError, + deleteCommandNotImplementedError, + duplicateCommandNotImplementedError, + updateNameCommandNotImplementedError, +} from "message_dict"; +import { Command } from "command"; +import { UndoRedoHandler } from "undoRedoHandler"; /** * Represents a Object in CANVAS */ export class CanvasObject extends Object3D { objectName; + #undoRedoHandler; + #rotatableAxis; + #isMovable; + #isSelectable; + #headerComponent; /** * Creates a new selectable object * @param {string} name the name of the object + * @param {string} defaultLabel the default label when no name is given + * @param {boolean} isMovable whether the object is movable + * @param {boolean} isSelectable whether the object is selectable + * @param {string[]} rotatableAxis containing all rotatable axis */ - constructor(name) { + constructor(name, defaultLabel, isMovable, isSelectable, rotatableAxis = []) { super(); this.objectName = name; - } + this.#undoRedoHandler = UndoRedoHandler.getInstance(); + this.#rotatableAxis = rotatableAxis; + this.#isMovable = isMovable; + this.#isSelectable = isSelectable; - /** - * Get a list of inspector components used for this object - * @abstract - * @throws {Error} Throws an error if the method is not implemented in subclasses. - * @returns {InspectorComponent[]} must be implemented in all subclasses - */ - get inspectorComponents() { - throw new Error(methodMustBeImplementedError); + this.#headerComponent = new HeaderInspectorComponent( + () => (this.objectName !== "" && this.objectName ? this.objectName : defaultLabel), + (newValue) => this.updateAndSaveObjectName(newValue), + this, + ); } /** - * Updates and saves the new name through a command - * @param {string} name the new name you want to save and update + * Update and save the name of the object + * @param {string} name the new name + * @returns {void} */ - // eslint-disable-next-line no-unused-vars -- required for interface compatibility updateAndSaveObjectName(name) { - throw new Error(methodMustBeImplementedError); + const UpdatePropertyCommand = this.updatePropertyCommand; + if (!UpdatePropertyCommand) { + throw new Error(updateNameCommandNotImplementedError); + } + + this.#undoRedoHandler.executeCommand(new UpdatePropertyCommand(this, "objectName", name)); } /** @@ -75,46 +96,91 @@ export class CanvasObject extends Object3D { } /** - * Duplicates the object + * Duplicate the object + * @returns {void} */ duplicate() { - throw new Error(methodMustBeImplementedError); + const DuplicateCommand = this.duplicateCommand; + if (!DuplicateCommand) { + throw new Error(duplicateCommandNotImplementedError); + } + + this.#undoRedoHandler.executeCommand(new DuplicateCommand(this)); } + /** * Deletes the object */ delete() { + const DeleteCommand = this.deleteCommand; + if (!DeleteCommand) { + throw new Error(deleteCommandNotImplementedError); + } + + this.#undoRedoHandler.executeCommand(new DeleteCommand(this)); + } + + /** + * Get the inspectorComponents used for this object + * The child classes should extend this method to add their own components + * @returns {InspectorComponent[]} array of the inspectorComponents used + */ + get inspectorComponents() { + return [this.#headerComponent]; + } + + /** + * Returns the command class used to update the name of the object + * @abstract + * @throws {Error} Throws an error if the method is not implemented in subclasses. + * @returns {new (...args: any[]) => Command} the command class used to update the name + */ + get updatePropertyCommand() { throw new Error(methodMustBeImplementedError); } /** - * Returns the axis on which the object is rotatable + * Returns the command class used to duplicate the object * @abstract * @throws {Error} - Throws an error if the method is not implemented in subclasses. - * @returns {string[]} array containing all rotatable axis. + * @returns {new (...args: any[]) => Command} the command class used to duplicate the object */ - get rotatableAxis() { + get duplicateCommand() { throw new Error(methodMustBeImplementedError); } /** - * Returns whether the object is movable or not + * Returns the command class used to delete the object * @abstract * @throws {Error} - Throws an error if the method is not implemented in subclasses. + * @returns {new (...args: any[]) => Command} the command class used to delete the object + */ + get deleteCommand() { + throw new Error(methodMustBeImplementedError); + } + + /** + * Returns the rotatable axis of the object + * @returns {string[]} containing all rotatable axis + */ + get rotatableAxis() { + return this.#rotatableAxis; + } + + /** + * Returns whether an object is movable or not * @returns {boolean} whether the object is movable */ get isMovable() { - throw new Error(methodMustBeImplementedError); + return this.#isMovable; } /** * Returns whether an object is selectable or not - * @abstract - * @throws {Error} - Throws an error if the method is not implemented in subclasses. * @returns {boolean} whether the object is selectable */ get isSelectable() { - throw new Error(methodMustBeImplementedError); + return this.#isSelectable; } /** @@ -136,6 +202,14 @@ export class CanvasObject extends Object3D { get lastRotation() { throw new Error(methodMustBeImplementedError); } + + /** + * Returns the undoRedoHandler used for this object + * @returns {import("undoRedoHandler").UndoRedoHandler} the undoRedoHandler + */ + get undoRedoHandler() { + return this.#undoRedoHandler; + } } /** diff --git a/canvas_editor/static/js/editor/objects/heliostat.mjs b/canvas_editor/static/js/editor/objects/heliostat.mjs index f4ea76fa..d2b0a222 100644 --- a/canvas_editor/static/js/editor/objects/heliostat.mjs +++ b/canvas_editor/static/js/editor/objects/heliostat.mjs @@ -1,16 +1,11 @@ import { CanvasObject, loadGltf } from "canvasObject"; import { DeleteHeliostatCommand } from "deleteCommands"; import { DuplicateHeliostatCommand } from "duplicateCommands"; -import { - HeaderInspectorComponent, - InputFieldInspectorComponent, - MultiFieldInspectorComponent, - InspectorComponent, -} from "inspectorComponents"; -import { Vector3 } from "three"; -import { UndoRedoHandler } from "undoRedoHandler"; +import { InspectorComponent } from "inspectorComponents"; import { UpdateHeliostatCommand } from "updateCommands"; import * as THREE from "three"; +import { Command } from "command"; +import { MovableCanvasObject } from "movableCanvasObjects"; /** * Class that represents the Heliostat object @@ -21,15 +16,11 @@ export class Heliostat extends CanvasObject { * @type {number} */ apiID; - #headerComponent; - #positionComponent; - #undoRedoHandler = UndoRedoHandler.getInstance(); - #isMovable = true; + /** - * @type { string[] } + * @type {MovableCanvasObject} */ - #rotatableAxis = null; - #lastPosition; + #movement; /** * Creates a Heliostat object @@ -38,134 +29,71 @@ export class Heliostat extends CanvasObject { * @param {number} [apiID] The id for api usage */ constructor(heliostatName, position, apiID = null) { - super(heliostatName); + super(heliostatName, "Heliostat", true, true, null); loadGltf("/static/models/heliostat.glb", this, true); this.position.copy(position); - this.#lastPosition = new Vector3(position.x, position.y, position.z); this.apiID = apiID; - // create components for inspector - this.#headerComponent = new HeaderInspectorComponent( - () => (this.objectName !== "" && this.objectName ? this.objectName : "Heliostat"), - (name) => this.updateAndSaveObjectName(name), - this, - ); - - const nCoordinate = new InputFieldInspectorComponent( - "N", - "number", - () => this.position.x, - (newValue) => { - this.#undoRedoHandler.executeCommand( - new UpdateHeliostatCommand(this, "position", new Vector3(newValue, this.position.y, this.position.z)), - ); - }, - -Infinity, - ); - - const uCoordinate = new InputFieldInspectorComponent( - "U", - "number", - () => this.position.y, - (newValue) => { - this.#undoRedoHandler.executeCommand( - new UpdateHeliostatCommand(this, "position", new Vector3(this.position.x, newValue, this.position.z)), - ); - }, - 0, - ); - - const eCoordinate = new InputFieldInspectorComponent( - "E", - "number", - () => this.position.z, - (newValue) => { - this.#undoRedoHandler.executeCommand( - new UpdateHeliostatCommand(this, "position", new Vector3(this.position.x, this.position.y, newValue)), - ); - }, - -Infinity, - ); - - this.#positionComponent = new MultiFieldInspectorComponent("Position", [nCoordinate, uCoordinate, eCoordinate]); + /** + * @type {MovableCanvasObject} + */ + this.#movement = new MovableCanvasObject(this, position, UpdateHeliostatCommand); + this.updatePosition(position); } /** - * Updates the position of the heliostat - * @param {THREE.Vector3} position the new position + * Returns the command class used to update the name of the object + * @returns {new (...args: any[]) => Command} the command class used to update the name */ - updatePosition(position) { - this.position.copy(position); - this.#lastPosition = new Vector3(position.x, position.y, position.z); + get updatePropertyCommand() { + return UpdateHeliostatCommand; } /** - * Update and save the name of the object - * @param {string} name the new name for the object + * Returns the command class used to duplicate the object + * @returns {new (...args: any[]) => Command} the command class used to duplicate the object */ - updateAndSaveObjectName(name) { - this.#undoRedoHandler.executeCommand(new UpdateHeliostatCommand(this, "objectName", name)); + get duplicateCommand() { + return DuplicateHeliostatCommand; } /** - * Duplicate the object + * Returns the command class used to delete the object + * @returns {new (...args: any[]) => Command} the command class used to delete the object */ - duplicate() { - this.#undoRedoHandler.executeCommand(new DuplicateHeliostatCommand(this)); + get deleteCommand() { + return DeleteHeliostatCommand; } /** - * Delete the object + * Call the movableCanvasObject to update the position + * @param {THREE.Vector3} position the new position of the heliostat */ - delete() { - this.#undoRedoHandler.executeCommand(new DeleteHeliostatCommand(this)); + updatePosition(position) { + this.#movement.updatePosition(position); } - /** - * Updates the position of the heliostat - * @param {Vector3} position - the new position of the heliostat + * Call the movableCanvasObject to update and save the position + * @param {THREE.Vector3} position the new position of the heliostat */ updateAndSaveObjectPosition(position) { - this.#undoRedoHandler.executeCommand(new UpdateHeliostatCommand(this, "position", position)); - } - - /** - * Get an array of all inspectorComponents for this object - * @returns {InspectorComponent[]} array of inspectorComponents - */ - get inspectorComponents() { - return [this.#headerComponent, this.#positionComponent]; - } - - /** - * Get an array containing all rotatable axis - * @returns {string[]} containing all rotatable axis - */ - get rotatableAxis() { - return this.#rotatableAxis; - } - - /** - * Get whether the object is selectable - * @returns {boolean} whether the object is selectable - */ - get isSelectable() { - return true; + this.#movement.updateAndSaveObjectPosition(position); } /** - * Get whether the object is movable - * @returns {boolean} whether the object is movable + * Get the last positon of the object from the movableCanvasObject + * @returns {THREE.Vector3} the last position of the object */ - get isMovable() { - return this.#isMovable; + get lastPosition() { + return this.#movement.lastPosition; } - /** - * Get the current position of the object - * @returns {THREE.Vector3} the position of the object + * Get the inspectorComponents used for this object + * The inspector components are included by the canvas objects + * The position inspector components are included by the movableCanvasObject + * @returns {InspectorComponent[]} array of inspectorComponents */ - get lastPosition() { - return this.#lastPosition; + get inspectorComponents() { + return [...super.inspectorComponents, ...this.#movement.inspectorComponents]; } } diff --git a/canvas_editor/static/js/editor/objects/lightSource.mjs b/canvas_editor/static/js/editor/objects/lightSource.mjs index c1bb9469..a337e1e6 100644 --- a/canvas_editor/static/js/editor/objects/lightSource.mjs +++ b/canvas_editor/static/js/editor/objects/lightSource.mjs @@ -1,12 +1,8 @@ import { CanvasObject } from "canvasObject"; +import { Command } from "command"; import { DeleteLightSourceCommand } from "deleteCommands"; import { DuplicateLightSourceCommand } from "duplicateCommands"; -import { - HeaderInspectorComponent, - InputFieldInspectorComponent, - SelectFieldInspectorComponent, - InspectorComponent, -} from "inspectorComponents"; +import { SelectFieldInspectorComponent, InspectorComponent, InputFieldInspectorComponent } from "inspectorComponents"; import { UndoRedoHandler } from "undoRedoHandler"; import { UpdateLightsourceCommand } from "updateCommands"; @@ -36,7 +32,6 @@ export class LightSource extends CanvasObject { */ distributionCovariance; - #header; #numberOfRaysComponent; #lightsourceTypeComponent; #distributionTypeComponent; @@ -44,8 +39,6 @@ export class LightSource extends CanvasObject { #distributionCovarianceComponent; #undoRedoHandler = UndoRedoHandler.getInstance(); - #isMovable = false; - #rotatableAxis = null; /** * Create the light source object @@ -66,7 +59,7 @@ export class LightSource extends CanvasObject { distributionCovariance, apiID = null, ) { - super(lightSourceName); + super(lightSourceName, "Light Source", false, false); this.apiID = apiID; this.numberOfRays = numberOfRays; this.lightSourceType = lightSourceType; @@ -74,12 +67,6 @@ export class LightSource extends CanvasObject { this.distributionMean = distributionMean; this.distributionCovariance = distributionCovariance; - this.#header = new HeaderInspectorComponent( - () => (this.objectName !== "" && this.objectName ? this.objectName : "Light source"), - (newValue) => this.updateAndSaveObjectName(newValue), - this, - ); - this.#numberOfRaysComponent = new InputFieldInspectorComponent( "Number of rays", "number", @@ -130,57 +117,37 @@ export class LightSource extends CanvasObject { } /** - * Update and save the name of the object - * @param {string} name the new name - */ - updateAndSaveObjectName(name) { - this.#undoRedoHandler.executeCommand(new UpdateLightsourceCommand(this, "objectName", name)); - } - - /** - * Duplicate the object - */ - duplicate() { - this.#undoRedoHandler.executeCommand(new DuplicateLightSourceCommand(this)); - } - /** - * Delete the object - */ - delete() { - this.#undoRedoHandler.executeCommand(new DeleteLightSourceCommand(this)); - } - - /** - * Returns whether the light source is rotatable or not - * @returns {string[]} false, as the light source is not rotatable + * Returns the command class used to update the name of the object + * @returns {new (...args: any[]) => Command} the command class used to update the name */ - get rotatableAxis() { - return this.#rotatableAxis; + get updatePropertyCommand() { + return UpdateLightsourceCommand; } /** - * Returns whether the light source is movable or not - * @returns {boolean} false, as the light source is movable + * Returns the command class used to duplicate the object + * @returns {new (...args: any[]) => Command} the command class used to duplicate the object */ - get isMovable() { - return this.#isMovable; + get duplicateCommand() { + return DuplicateLightSourceCommand; } /** - * Get whether the object is selectable - * @returns {boolean} if the object is selectable + * Returns the command class used to delete the object + * @returns {new (...args: any[]) => Command} the command class used to delete the object */ - get isSelectable() { - return false; + get deleteCommand() { + return DeleteLightSourceCommand; } /** * Get an array of all inspectorComponents used for this object + * The inspectorComponents from the parent class are also included * @returns {InspectorComponent[]} array of all inspectorComponents */ get inspectorComponents() { return [ - this.#header, + ...super.inspectorComponents, this.#numberOfRaysComponent, this.#lightsourceTypeComponent, this.#distributionTypeComponent, diff --git a/canvas_editor/static/js/editor/objects/movableCanvasObjects.mjs b/canvas_editor/static/js/editor/objects/movableCanvasObjects.mjs new file mode 100644 index 00000000..c6f5aa56 --- /dev/null +++ b/canvas_editor/static/js/editor/objects/movableCanvasObjects.mjs @@ -0,0 +1,118 @@ +import { CanvasObject } from "canvasObject"; +import { Command } from "command"; +import { InspectorComponent, MultiFieldInspectorComponent, SingleFieldInspectorComponent } from "inspectorComponents"; +import { Vector3 } from "three"; + +/** + * Class that represents movable canvas objects + * For now this includes Heliostats and Receivers + */ +export class MovableCanvasObject { + #target; + #positionComponent; + #lastPosition; + /** + * @type {new (...args: any[]) => Command} + */ + #updatePropertyCommand; + + /** + * The constructor of the movable canvas object + * @param {CanvasObject} target the target object + * @param {Vector3} position the initial position + * @param {new (...args: any[]) => Command} updatePropertyCommand the command class used to update the position + */ + constructor(target, position, updatePropertyCommand) { + this.#target = target; + this.#lastPosition = new Vector3(position.x, position.y, position.z); + this.#updatePropertyCommand = updatePropertyCommand; + + const nCoordinate = new SingleFieldInspectorComponent( + "N", + "number", + () => this.#target.position.x, + (newValue) => { + this.#target.undoRedoHandler.executeCommand( + new this.#updatePropertyCommand( + this.#target, + "position", + new Vector3(newValue, this.#target.position.y, this.#target.position.z), + ), + ); + }, + -Infinity, + ); + + const uCoordinate = new SingleFieldInspectorComponent( + "U", + "number", + () => this.#target.position.y, + (newValue) => { + this.#target.undoRedoHandler.executeCommand( + new this.#updatePropertyCommand( + this.#target, + "position", + new Vector3(this.#target.position.x, newValue, this.#target.position.z), + ), + ); + }, + 0, + ); + + const eCoordinate = new SingleFieldInspectorComponent( + "E", + "number", + () => this.#target.position.z, + (newValue) => { + this.#target.undoRedoHandler.executeCommand( + new this.#updatePropertyCommand( + this.#target, + "position", + new Vector3(this.#target.position.x, this.#target.position.y, newValue), + ), + ); + }, + -Infinity, + ); + + this.#positionComponent = new MultiFieldInspectorComponent("Position", [nCoordinate, uCoordinate, eCoordinate]); + } + + /** + * Updates the position of the object + * + * Should only be used for internal updates (like inside commands) + * @param {Vector3} position the new position + */ + updatePosition(position) { + this.#target.position.copy(position); + this.#lastPosition = new Vector3(position.x, position.y, position.z); + } + + /** + * Updates the position of the object + * and saves the change using the undoRedoHandler + * + * Use this method whenever the user intentionally changes a value and the change + * should be undoable, saved, and reflected in the UI. + * @param {Vector3} position - the new position of the object + */ + updateAndSaveObjectPosition(position) { + this.#target.undoRedoHandler.executeCommand(new this.#updatePropertyCommand(this.#target, "position", position)); + } + /** + * Get the current position of the object + * @returns {Vector3} the position of the object + */ + get lastPosition() { + return this.#lastPosition; + } + + /** + * Get an array of all inspectorComponents used for this object + * @returns {InspectorComponent[]} array of all inspectorComponents + */ + get inspectorComponents() { + return [this.#positionComponent]; + } +} diff --git a/canvas_editor/static/js/editor/objects/receiver.mjs b/canvas_editor/static/js/editor/objects/receiver.mjs index cc3edd12..1e0efc56 100644 --- a/canvas_editor/static/js/editor/objects/receiver.mjs +++ b/canvas_editor/static/js/editor/objects/receiver.mjs @@ -2,18 +2,18 @@ import { CanvasObject, loadGltf } from "canvasObject"; import { DeleteReceiverCommand } from "deleteCommands"; import { DuplicateReceiverCommand } from "duplicateCommands"; import { - HeaderInspectorComponent, - InputFieldInspectorComponent, MultiFieldInspectorComponent, SelectFieldInspectorComponent, InspectorComponent, + InputFieldInspectorComponent, } from "inspectorComponents"; import { Object3D, Vector3 } from "three"; import { UndoRedoHandler } from "undoRedoHandler"; import { UpdateReceiverCommand } from "updateCommands"; import * as THREE from "three"; import { towerBasePath, towerTopPath } from "path_dict"; - +import { Command } from "command"; +import { MovableCanvasObject } from "movableCanvasObjects"; /** * Class that represents the receiver object */ @@ -56,19 +56,19 @@ export class Receiver extends CanvasObject { curvatureU; #undoRedoHandler = UndoRedoHandler.getInstance(); + /** + * @type {MovableCanvasObject} + */ + #movement; + #top; #base; - #headerComponent; - #positionComponent; #normalVectorComponent; #towerTypeComponent; #curvatureComponent; #planeComponent; #resolutionComponent; - #isMovable = true; - #rotatableAxis = null; - #lastPosition; /** * Creates a Receiver object @@ -97,7 +97,7 @@ export class Receiver extends CanvasObject { curvatureU, apiID = null, ) { - super(receiverName); + super(receiverName, "Receiver", true, true, null); // place the 3D object this.#base = new ReceiverBase(); this.add(this.#base); @@ -105,8 +105,6 @@ export class Receiver extends CanvasObject { this.#top = new ReceiverTop(); this.add(this.#top); - this.updatePosition(position); - this.apiID = apiID; this.towerType = towerType; this.normalVector = normalVector; @@ -116,52 +114,9 @@ export class Receiver extends CanvasObject { this.resolutionU = resolutionU; this.curvatureE = curvatureE; this.curvatureU = curvatureU; - this.#lastPosition = new Vector3(position.x, position.y, position.z); - - // create components for the inspector - this.#headerComponent = new HeaderInspectorComponent( - () => (this.objectName !== "" && this.objectName ? this.objectName : "Receiver"), - (name) => this.updateAndSaveObjectName(name), - this, - ); - - const nCoordinate = new InputFieldInspectorComponent( - "N", - "number", - () => this.lastPosition.x, - (newValue) => { - this.#undoRedoHandler.executeCommand( - new UpdateReceiverCommand(this, "position", new Vector3(newValue, this.position.y, this.position.z)), - ); - }, - -Infinity, - ); - - const uCoordinate = new InputFieldInspectorComponent( - "U", - "number", - () => this.lastPosition.y, - (newValue) => { - this.#undoRedoHandler.executeCommand( - new UpdateReceiverCommand(this, "position", new Vector3(this.position.x, newValue, this.position.z)), - ); - }, - 0, - ); - const eCoordinate = new InputFieldInspectorComponent( - "E", - "number", - () => this.lastPosition.z, - (newValue) => { - this.#undoRedoHandler.executeCommand( - new UpdateReceiverCommand(this, "position", new Vector3(this.position.x, this.position.y, newValue)), - ); - }, - -Infinity, - ); - - this.#positionComponent = new MultiFieldInspectorComponent("Position", [nCoordinate, uCoordinate, eCoordinate]); + this.#movement = new MovableCanvasObject(this, position, UpdateReceiverCommand); + this.updatePosition(position); const nNormalVector = new InputFieldInspectorComponent( "N", @@ -301,86 +256,64 @@ export class Receiver extends CanvasObject { this.#base.position.y = y; } - /** - * Updates the position of the receiver - * @param {Vector3} position - the new position of the receiver - */ - updateAndSaveObjectPosition(position) { - this.#undoRedoHandler.executeCommand(new UpdateReceiverCommand(this, "position", position)); - } - /** * Updates the receiver’s position by adjusting both the base and the top, ensuring that the base remains on the ground. * @param {THREE.Vector3} position the new position of the receiver */ updatePosition(position) { - this.position.copy(position); - this.#lastPosition = new Vector3(position.x, position.y, position.z); + this.#movement.updatePosition(position); this.#base.position.y = -position.y; } /** - * Update and save the name of the object - * @param {string} name the new name - */ - updateAndSaveObjectName(name) { - this.#undoRedoHandler.executeCommand(new UpdateReceiverCommand(this, "objectName", name)); - } - - /** - * Deletes the receiver + * Returns the command class used to update the name of the object + * @returns {new (...args: any[]) => Command} the command class used to update the name */ - delete() { - this.#undoRedoHandler.executeCommand(new DeleteReceiverCommand(this)); + get updatePropertyCommand() { + return UpdateReceiverCommand; } /** - * Duplicates the receiver + * Returns the command class used to delete the object + * @returns {new (...args: any[]) => Command} the command class used to delete the object */ - duplicate() { - this.#undoRedoHandler.executeCommand(new DuplicateReceiverCommand(this)); + get deleteCommand() { + return DeleteReceiverCommand; } /** - * Get all rotatable axis - * @returns {string[]} containing all rotatable axis + * Returns the command class used to duplicate the object + * @returns {new (...args: any[]) => Command} the command class used to duplicate the object */ - get rotatableAxis() { - return this.#rotatableAxis; + get duplicateCommand() { + return DuplicateReceiverCommand; } /** - * Get whether the object is movable or not - * @returns {boolean} whether the object is movable + * Call the movableCanvasObject to update and save the position + * @param {THREE.Vector3} position the new position of the heliostat */ - get isMovable() { - return this.#isMovable; - } - - /** - * Get whether the object is selectable - * @returns {boolean} whether the object is selectable - */ - get isSelectable() { - return true; + updateAndSaveObjectPosition(position) { + this.#movement.updateAndSaveObjectPosition(position); } /** - * Get the current position of the object - * @returns {THREE.Vector3} the current position + * Get the last positon of the object from the movableCanvasObject + * @returns {THREE.Vector3} the last position of the object */ get lastPosition() { - return this.#lastPosition; + return this.#movement.lastPosition; } - /** * Get the inspectorComponents used for this object + * Get the HeaderComponent from the super class canvasObject + * Get the InspectorComponents from the movableCanvasObject * @returns {InspectorComponent[]} array of the inspectorComponents used */ get inspectorComponents() { return [ - this.#headerComponent, - this.#positionComponent, + ...super.inspectorComponents, + ...this.#movement.inspectorComponents, this.#normalVectorComponent, this.#towerTypeComponent, this.#curvatureComponent, diff --git a/canvas_editor/static/js/message_dict.js b/canvas_editor/static/js/message_dict.js index 35999025..3888b458 100644 --- a/canvas_editor/static/js/message_dict.js +++ b/canvas_editor/static/js/message_dict.js @@ -10,3 +10,6 @@ export const methodMustBeImplementedError = "This method must be implemented in export const invalidCompassStyleError = "Invalid compass style specified"; export const projectIdRequiredError = "When executing get instance for the first time the project id is needed"; export const errorUploadingFile = "Error uploading file:"; +export const updateNameCommandNotImplementedError = "updateNameCommand not implemented"; +export const duplicateCommandNotImplementedError = "duplicateCommand not implemented"; +export const deleteCommandNotImplementedError = "deleteCommand not implemented";