import { GlobalState } from '../globalState'; import { Nullable } from 'babylonjs/types'; import { Observer } from 'babylonjs/Misc/observable'; import { WorkbenchComponent, FramePortData } from './workbench'; import { Control } from 'babylonjs-gui/2D/controls/control'; import { Vector2 } from 'babylonjs/Maths/math.vector'; import { Container } from 'babylonjs-gui/2D/controls/container'; import { _ThinInstanceDataStorage } from 'babylonjs'; import { ContainerPropertyTabComponent } from './properties/containterPropertyComponent'; import * as React from 'react'; export class GUINode { private _x = 0; private _y = 0; private _gridAlignedX = 0; private _gridAlignedY = 0; private _globalState: GlobalState; private _onSelectionChangedObserver: Nullable>>; private _onSelectionBoxMovedObserver: Nullable>; private _onUpdateRequiredObserver: Nullable>; private _ownerCanvas: WorkbenchComponent; private _isSelected: boolean; private _isVisible = true; private _enclosingFrameId = -1; private _isContainer = false; public children: GUINode[] = []; public get isVisible() { return this._isVisible; } public set isVisible(value: boolean) { this._isVisible = value; } public get gridAlignedX() { return this._gridAlignedX; } public get gridAlignedY() { return this._gridAlignedY; } public get x() { return this._x; } public set x(value: number) { if (this._x === value) { return; } this._x = value; this._gridAlignedX = this._ownerCanvas.getGridPosition(value); } public get y() { return this._y; } public set y(value: number) { if (this._y === value) { return; } this._y = value; this._gridAlignedY = this._ownerCanvas.getGridPosition(value); } public get width() { return this.guiControl.widthInPixels; } public get height() { return this.guiControl.heightInPixels; } public get id() { return this.guiControl.uniqueId; } public get name() { return this.guiControl.name; } public get isSelected() { return this._isSelected; } public get enclosingFrameId() { return this._enclosingFrameId; } public set enclosingFrameId(value: number) { this._enclosingFrameId = value; } public set isSelected(value: boolean) { this._isSelected = value; if (value) { this._globalState.onSelectionChangedObservable.notifyObservers(this); } } public constructor(globalState: GlobalState, public guiControl: Control) { this._globalState = globalState; this._ownerCanvas = this._globalState.workbench; this.x = guiControl.leftInPixels; this.y = guiControl.topInPixels; guiControl.onPointerUpObservable.add(evt => { this.clicked = false; console.log("up"); }); guiControl.onPointerDownObservable.add( evt => { if(!this._ownerCanvas.isUp) return; this.clicked = true; this.isSelected = true; console.log("down"); this._ownerCanvas.isUp = false; } ); guiControl.onPointerEnterObservable.add( evt => { this._ownerCanvas.isOverGUINode = true; console.log("in"); } ); guiControl.onPointerOutObservable.add( evt => { this._ownerCanvas.isOverGUINode = false; console.log("out"); } ); this._isContainer = this.isContainer(); //TODO: Implement this._onSelectionBoxMovedObserver = this._globalState.onSelectionBoxMoved.add(rect1 => { }); } public cleanAccumulation(useCeil = false) { this.x = this._ownerCanvas.getGridPosition(this.x, useCeil); this.y = this._ownerCanvas.getGridPosition(this.y, useCeil); } public clicked: boolean; public _onMove(evt: Vector2, startPos: Vector2, ignorClick: boolean = false) { if(!this.clicked && !ignorClick) return false; console.log("moving"); //TODO: Implement move with zoom factor. let newX = (evt.x - startPos.x) ;// / this._ownerCanvas.zoom; let newY = (evt.y - startPos.y) ;// / this._ownerCanvas.zoom; this.x += newX; this.y += newY; this.children.forEach(child => { child._onMove(evt, startPos, true); }); return true; //evt.stopPropagation(); } renderContainer(): React.ReactNode { if(!this._isContainer) return null; return React.createElement(ContainerPropertyTabComponent, { globalState: this._globalState, guiNode: this }); } public updateVisual() { this.guiControl.leftInPixels = this.x; this.guiControl.topInPixels = this.y; } private isContainer() { switch (this.guiControl.typeName) { case "Button": case "StackPanel": case "Rectangle": case "Ellipse": return true; default: return false; } } public addGui(childNode: GUINode) { if(!this._isContainer) return; this.children.push(childNode); (this.guiControl as Container).addControl(childNode.guiControl); //adjust the position to be relative //childNode.x = this.x - childNode.x; //childNode.y = this.y - childNode.y; } public dispose() { // notify frame observers that this node is being deleted this._globalState.onGuiNodeRemovalObservable.notifyObservers(this); if (this._onSelectionChangedObserver) { this._globalState.onSelectionChangedObservable.remove(this._onSelectionChangedObserver); } if (this._onUpdateRequiredObserver) { this._globalState.onUpdateRequiredObservable.remove(this._onUpdateRequiredObserver); } if (this._onSelectionBoxMovedObserver) { this._globalState.onSelectionBoxMoved.remove(this._onSelectionBoxMovedObserver); } this.guiControl.dispose(); } }