Skip to content

Commit

Permalink
Added first representation of cube selection state.
Browse files Browse the repository at this point in the history
  • Loading branch information
ffrank913 committed Jul 9, 2024
1 parent c012654 commit f3c87ea
Show file tree
Hide file tree
Showing 6 changed files with 420 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/grid/Grid.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GRID_SIDE_LINE_COLOR, GRID_CENTER_LINE_COLOR } from "../constant/GridColors.ts";
import { HELPER_LAYER_MASK } from "../constant/VisibilityLayerMask.ts";
import { UI_LAYER_MASK } from "../constant/VisibilityLayerMask.ts";
import { GridHelper, Object3D } from "three";

/**
Expand All @@ -15,7 +15,7 @@ export default class DIVEGrid extends Object3D {

const grid = new GridHelper(100, 100, GRID_CENTER_LINE_COLOR, GRID_SIDE_LINE_COLOR);
grid.material.depthTest = false;
grid.layers.mask = HELPER_LAYER_MASK;
grid.layers.mask = UI_LAYER_MASK;

this.add(grid);
}
Expand Down
93 changes: 93 additions & 0 deletions src/selections/cubeselection/CubeSelection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Box3, Object3D } from "three";
import { DIVECubeSelectionMesh } from "./mesh/CubeSelectionMesh";

export class DIVECubeSelection extends Object3D {
private _parents: { [id: string]: Object3D };
private _objectRoot: Object3D;

private _boundingBox: Box3;
private _boxMesh: DIVECubeSelectionMesh;

public get objects(): Object3D[] {
return this._objectRoot.children;
}

public set objects(objects: Object3D[]) {
this._objectRoot.children = objects;
this.calculateBoundingBox();
this._boxMesh.updateBox(this._boundingBox);
}

constructor() {
super();

this._parents = {};
this._objectRoot = new Object3D();
this.add(this._objectRoot);

this._boundingBox = new Box3()
this._boxMesh = new DIVECubeSelectionMesh();
this.add(this._boxMesh);

}

public Attach(object: Object3D): this {
if (object.parent !== null) {
this._parents[object.uuid] = object.parent;
}

this.addChild(object);

return this;
}

public Detach(object: Object3D): this;
public Detach(object: string): this;
public Detach(object: Object3D | string): this {
if (typeof object === 'string') {
const index = this.children.findIndex((child) => child.uuid === object);
if (index === -1) return this;

if (this._parents[object]) {
this.removeChild(this.children[index]);
this._parents[object].add(this.children[index]);
delete this._parents[object];
} else {
this.removeChild(this.children[index]);
}
} else {
if (this._parents[object.uuid]) {
this.removeChild(object);
this._parents[object.uuid].add(object);
delete this._parents[object.uuid];
} else {
this.removeChild(object);
}
}

return this;
}

private addChild(object: Object3D): this {
this._objectRoot.add(object);
this.calculateBoundingBox();
this._boxMesh.updateBox(this._boundingBox);

return this;
}

private removeChild(object: Object3D): this {
this._objectRoot.remove(object);
this.calculateBoundingBox();
this._boxMesh.updateBox(this._boundingBox);
return this;
}

private calculateBoundingBox(): void {
this._objectRoot.children.forEach((child) => {
child.updateMatrixWorld(true);
});

this._boundingBox.setFromObject(this._objectRoot);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Line2, LineGeometry, LineMaterial } from 'three/examples/jsm/Addons';
import { HELPER_LAYER_MASK } from '../../../../constant/VisibilityLayerMask';
import { Color } from 'three';

export class DIVECubeSelectionEdgeHandle extends Line2 {
readonly isCubeSelection = true;
readonly isCubeSelectionEdge = true;

private _color: number;
private _hoverColor: number = 0xff0000;

constructor(material: LineMaterial) {
super();

this.layers.mask = HELPER_LAYER_MASK;

this.geometry = new LineGeometry();
this.material = material.clone();
this._color = this.material.color.getHex();

const hsl = new Color(this._color).getHSL({ h: 0, s: 0, l: 0 });
this._hoverColor = new Color(this._color).setHSL(hsl.h, hsl.s, hsl.l * 1.3).getHex();
}

public setPoints(points: [number, number, number, number, number, number]): this {
this.geometry.setPositions(points);
this.geometry.computeBoundingBox();
return this;
}

public onPointerEnter(): void {
this.material.color.setHex(this._hoverColor);
}

public onPointerLeave(): void {
this.material.color.setHex(this._color);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Color, Mesh, MeshBasicMaterial, PlaneGeometry, Vector3, HSL } from 'three';
import { HELPER_LAYER_MASK } from '../../../../constant/VisibilityLayerMask';

export class DIVECubeSelectionPlaneHandle extends Mesh {
readonly isCubeSelection = true;
readonly isCubeSelectionPlane = true;

private _color: number;
private _hoverColor: number = 0xff0000;

constructor(material: MeshBasicMaterial) {
super();

this.layers.mask = HELPER_LAYER_MASK;
this.geometry = new PlaneGeometry();

this.material = material.clone();
this._color = material.color.getHex();

const hsl: HSL = {
h: 0,
s: 0,
l: 0,
};
new Color(this._color).getHSL(hsl);
this._hoverColor = new Color(this._color).setHSL(hsl.h, hsl.s, hsl.l * 1.2).getHex();


}

public setPoints(points: [Vector3, Vector3, Vector3, Vector3]): this {
this.geometry.setFromPoints(points);
this.geometry.computeBoundingBox();
return this;
}

public onPointerEnter(): void {
(this.material as MeshBasicMaterial).color.setHex(this._hoverColor);
}

public onPointerLeave(): void {
(this.material as MeshBasicMaterial).color.setHex(this._color);
}
}
164 changes: 164 additions & 0 deletions src/selections/cubeselection/mesh/CubeSelectionMesh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { Box3, Color, MeshBasicMaterial, Object3D, Vector3 } from 'three';
import { LineMaterial } from 'three/examples/jsm/Addons';
import { DIVECubeSelectionPlaneHandle } from '../handle/plane/CubeSelectionPlaneHandle';
import { DIVECubeSelectionEdgeHandle } from '../handle/edge/CubeSelectionEdgeHandle';

export class DIVECubeSelectionMesh extends Object3D {
private _planeMaterial: MeshBasicMaterial;
private _lineMaterial: LineMaterial;

/**
* Order: posX, negX, posY, negY, posZ, negZ
*/
private _planes: DIVECubeSelectionPlaneHandle[] = [];
public get planes(): DIVECubeSelectionPlaneHandle[] {
return this._planes;
}

private _planesNode: Object3D;
private _edgesNode: Object3D;

constructor() {
super();

this._planeMaterial = new MeshBasicMaterial({
color: 0x4e5cff,
transparent: true,
opacity: 0.2,
});

this._planesNode = new Object3D();
this.add(this._planesNode);

const hsl = this._planeMaterial.color.getHSL({ h: 0, s: 0, l: 0 });
this._lineMaterial = new LineMaterial({
color: new Color().setHSL(hsl.h, hsl.s, hsl.l * 1.5).getHex(),
linewidth: 5, // in world units with size attenuation, pixels otherwise
vertexColors: false,
dashed: false,
alphaToCoverage: true,
});

this._edgesNode = new Object3D();
this.add(this._edgesNode);
}

public updateBox(box: Box3): void {
this.updateBoxMesh(box);
}

private updateBoxMesh(box: Box3): void {
this._planes = [];
this._planesNode.clear();
this._edgesNode.clear();

// when there are no children, set the geometry dimensions to 0
const size = new Vector3();
box.getSize(size);
if (size.length() === 0) return;

const center = new Vector3();
box.getCenter(center);
const width = box.max.x - box.min.x;
const height = box.max.y - box.min.y;
const depth = box.max.z - box.min.z;

this._planes = [
new DIVECubeSelectionPlaneHandle(this._planeMaterial).setPoints([ // posX
new Vector3(width / 2, height / 2, - depth / 2),
new Vector3(width / 2, -height / 2, - depth / 2),
new Vector3(width / 2, height / 2, depth / 2),
new Vector3(width / 2, -height / 2, depth / 2),
]).translateX(center.x).translateY(center.y).translateZ(center.z),

new DIVECubeSelectionPlaneHandle(this._planeMaterial).setPoints([ // negX
new Vector3(-width / 2, height / 2, depth / 2),
new Vector3(-width / 2, -height / 2, depth / 2),
new Vector3(-width / 2, height / 2, - depth / 2),
new Vector3(-width / 2, -height / 2, - depth / 2),
]).translateX(center.x).translateY(center.y).translateZ(center.z),

new DIVECubeSelectionPlaneHandle(this._planeMaterial).setPoints([ // posY
new Vector3(-width / 2, height / 2, - depth / 2),
new Vector3(width / 2, height / 2, - depth / 2),
new Vector3(-width / 2, height / 2, depth / 2),
new Vector3(width / 2, height / 2, depth / 2),
]).translateX(center.x).translateY(center.y).translateZ(center.z),

new DIVECubeSelectionPlaneHandle(this._planeMaterial).setPoints([ // negY
new Vector3(-width / 2, -height / 2, - depth / 2),
new Vector3(-width / 2, -height / 2, depth / 2),
new Vector3(width / 2, -height / 2, - depth / 2),
new Vector3(width / 2, -height / 2, depth / 2),
]).translateX(center.x).translateY(center.y).translateZ(center.z),

new DIVECubeSelectionPlaneHandle(this._planeMaterial).setPoints([ // posZ
new Vector3(width / 2, -height / 2, depth / 2),
new Vector3(-width / 2, -height / 2, depth / 2),
new Vector3(width / 2, height / 2, depth / 2),
new Vector3(-width / 2, height / 2, depth / 2),
]).translateX(center.x).translateY(center.y).translateZ(center.z),

new DIVECubeSelectionPlaneHandle(this._planeMaterial).setPoints([ // negZ
new Vector3(-width / 2, height / 2, - depth / 2),
new Vector3(-width / 2, -height / 2, - depth / 2),
new Vector3(width / 2, height / 2, - depth / 2),
new Vector3(width / 2, -height / 2, - depth / 2),
]).translateX(center.x).translateY(center.y).translateZ(center.z),
];

this._planesNode.clear();
this._planesNode.add(...this._planes);

const points = [
width / 2, height / 2, depth / 2,
width / 2, height / 2, - depth / 2,

width / 2, - height / 2, depth / 2,
width / 2, - height / 2, - depth / 2,

- width / 2, height / 2, depth / 2,
- width / 2, height / 2, - depth / 2,

- width / 2, - height / 2, depth / 2,
- width / 2, - height / 2, - depth / 2,


width / 2, height / 2, depth / 2,
width / 2, - height / 2, depth / 2,

width / 2, height / 2, - depth / 2,
width / 2, - height / 2, - depth / 2,

- width / 2, height / 2, depth / 2,
- width / 2, - height / 2, depth / 2,

- width / 2, height / 2, - depth / 2,
- width / 2, - height / 2, - depth / 2,


width / 2, height / 2, depth / 2,
- width / 2, height / 2, depth / 2,

width / 2, height / 2, - depth / 2,
- width / 2, height / 2, - depth / 2,

width / 2, - height / 2, depth / 2,
- width / 2, - height / 2, depth / 2,

width / 2, - height / 2, - depth / 2,
- width / 2, - height / 2, - depth / 2,
];

points.forEach((point, index) => {
if (index % 6 === 0) {
const edge = new DIVECubeSelectionEdgeHandle(this._lineMaterial);
edge.setPoints([
points[index] + center.x, points[index + 1] + center.y, points[index + 2] + center.z,
points[index + 3] + center.x, points[index + 4] + center.y, points[index + 5] + center.z,
]);
this._edgesNode.add(edge);
}
});
}
}
Loading

0 comments on commit f3c87ea

Please sign in to comment.