2024-07-23 22:45:27 -04:00
|
|
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
// dep: add.array
|
|
|
|
|
// dep: add.three
|
|
|
|
|
// dep: moto.license
|
|
|
|
|
// dep: moto.client
|
|
|
|
|
// dep: mesh.object
|
|
|
|
|
// use: mesh.api
|
|
|
|
|
// use: mesh.util
|
|
|
|
|
// use: mesh.group
|
|
|
|
|
gapp.register("mesh.sketch", [], (root, exports) => {
|
|
|
|
|
|
|
|
|
|
const { MeshBasicMaterial, LineBasicMaterial, LineSegments, DoubleSide } = THREE;
|
2024-07-24 12:29:55 -04:00
|
|
|
const { PlaneGeometry, EdgesGeometry, SphereGeometry, Vector3, Mesh } = THREE;
|
2024-07-23 22:45:27 -04:00
|
|
|
const { mesh, moto } = root;
|
|
|
|
|
const { space } = moto;
|
|
|
|
|
|
|
|
|
|
const mapp = mesh;
|
|
|
|
|
const worker = moto.client.fn;
|
|
|
|
|
|
|
|
|
|
const material = {
|
|
|
|
|
plane: new MeshBasicMaterial({ color: 0x888888, side: DoubleSide, transparent: true, opacity: 0.25 }),
|
|
|
|
|
outline: new LineBasicMaterial({ color: 0x88dddd, side: DoubleSide, transparent: true, opacity: 0.25 }),
|
|
|
|
|
handle: new MeshBasicMaterial({ color: 0x88dddd, side: DoubleSide, transparent: true, opacity: 0.25 }),
|
|
|
|
|
highlight: new LineBasicMaterial({ color: 0x88ffdd, side: DoubleSide, transparent: true, opacity: 0.5 }),
|
|
|
|
|
selected: new MeshBasicMaterial({ color: 0x88aa88, side: DoubleSide, transparent: true, opacity: 0.25 }),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** 2D plane containing open and closed polygons which can be extruded **/
|
|
|
|
|
mesh.sketch = class MeshSketch extends mesh.object {
|
2024-07-24 12:29:55 -04:00
|
|
|
constructor(opt = {}) {
|
|
|
|
|
super(opt.id);
|
2024-07-23 22:45:27 -04:00
|
|
|
|
2024-07-24 12:29:55 -04:00
|
|
|
this.file = opt.file || this.id;
|
|
|
|
|
this.scale = opt.scale || { x: 10, y: 10 };
|
|
|
|
|
this.center = opt.center || { x: 0, y: 0, z: 0 };
|
|
|
|
|
this.normal = opt.normal || { x: 0, y: 0, z: 1 };
|
|
|
|
|
|
|
|
|
|
const planeGeometry = new PlaneGeometry(1, 1);
|
2024-07-23 22:45:27 -04:00
|
|
|
const planeMaterial = material.plane;
|
|
|
|
|
const plane = this.plane = new Mesh(planeGeometry, planeMaterial);
|
|
|
|
|
|
|
|
|
|
const outlineGeometry = new EdgesGeometry(planeGeometry);
|
|
|
|
|
const outlineMaterial = material.outline;
|
|
|
|
|
const outline = this.outline = new LineSegments(outlineGeometry, outlineMaterial);
|
|
|
|
|
plane.add(outline);
|
|
|
|
|
|
2024-07-24 12:29:55 -04:00
|
|
|
const handleGeometry = new SphereGeometry(0.05, 16, 16);
|
2024-07-23 22:45:27 -04:00
|
|
|
const handleMaterial = material.handle;
|
|
|
|
|
|
|
|
|
|
const handles = [];
|
2024-07-24 12:29:55 -04:00
|
|
|
const corners = [ [-0.5, 0.5, 0], [0.5, 0.5, 0], [-0.5, -0.5, 0], [0.5, -0.5, 0] ];
|
2024-07-23 22:45:27 -04:00
|
|
|
|
|
|
|
|
for (let corner of corners) {
|
|
|
|
|
const handle = new Mesh(handleGeometry, handleMaterial);
|
|
|
|
|
handle.position.set(...corner);
|
|
|
|
|
plane.add(handle);
|
|
|
|
|
handles.push(handle);
|
|
|
|
|
}
|
2024-07-24 12:29:55 -04:00
|
|
|
|
|
|
|
|
this.update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
update() {
|
|
|
|
|
const { plane, center, normal, scale, type } = this;
|
|
|
|
|
|
|
|
|
|
plane.scale.set(scale.x, scale.y, 1);
|
|
|
|
|
plane.position.set(center.x, center.y, center.z);
|
|
|
|
|
|
|
|
|
|
const normalVector = new Vector3(normal.x, normal.y, normal.z);
|
|
|
|
|
const targetPoint = new Vector3().addVectors(plane.position, normalVector);
|
|
|
|
|
plane.lookAt(targetPoint);
|
|
|
|
|
|
|
|
|
|
this.#db_save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#db_save() {
|
|
|
|
|
const { center, normal, scale, type, file } = this;
|
|
|
|
|
mapp.db.space.put(this.id, { center, normal, scale, type, file });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#db_remove() {
|
|
|
|
|
mapp.api.sketch.remove(this);
|
|
|
|
|
mapp.db.space.remove(this.id);
|
2024-07-23 22:45:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get type() {
|
|
|
|
|
return "sketch";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get object() {
|
|
|
|
|
return this.plane;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rename(newname) {
|
|
|
|
|
this.file = newname;
|
2024-07-24 12:29:55 -04:00
|
|
|
this.#db_save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remove() {
|
|
|
|
|
this.#db_remove();
|
2024-07-23 22:45:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
highlight() {
|
|
|
|
|
this.outline.material = material.highlight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unhighlight() {
|
|
|
|
|
this.outline.material = material.outline;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
select(bool) {
|
|
|
|
|
if (bool === undefined) {
|
|
|
|
|
return this.plane.material === material.selected;
|
|
|
|
|
}
|
|
|
|
|
if (bool.toggle) {
|
|
|
|
|
return this.select(!this.select());
|
|
|
|
|
}
|
|
|
|
|
return this.plane.material = (bool ? material.selected : material.plane);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
});
|