sort out sketch element dragging
This commit is contained in:
parent
9d991b0a97
commit
2eb3582eca
4 changed files with 113 additions and 48 deletions
|
|
@ -329,22 +329,34 @@ function space_init(data) {
|
|||
]);
|
||||
|
||||
// mouse hover/click handlers. required to enable model drag in space.js
|
||||
space.mouse.downSelect((int, event) => {
|
||||
// called two ways:
|
||||
// without args to return a list of selectable targets
|
||||
// with args when a selection is made
|
||||
space.mouse.downSelect((int, event, ints) => {
|
||||
if (int?.object?.sketch) {
|
||||
int.object.sketch.drag({ start: int.object });
|
||||
} else if (int?.object?.sketch_item) {
|
||||
int.object.sketch_item.sketch.drag({ start: int.object });
|
||||
}
|
||||
if (event?.shiftKey) {
|
||||
return api.objects();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return event && event.shiftKey ? api.objects() : undefined;
|
||||
});
|
||||
|
||||
// called two ways:
|
||||
// without args to return a list of selectable targets
|
||||
// with args when a selection is made
|
||||
space.mouse.upSelect((int, event, ints) => {
|
||||
if (ints?.length > 1) {
|
||||
// ensure sketch items are returned before sketch plane / handles
|
||||
let polys = ints.filter(i => i.object.poly);
|
||||
int = polys.length ? polys[0] : int;
|
||||
let els = ints.filter(i => i.object.sketch_item);
|
||||
int = els.length ? els[0] : int;
|
||||
}
|
||||
if (event && event.target.nodeName === "CANVAS") {
|
||||
const model = int?.object?.model;
|
||||
const sketch = int?.object?.sketch;
|
||||
if (event?.target?.nodeName === "CANVAS") {
|
||||
// a selection was made
|
||||
const { model, sketch, sketch_item } = int?.object || {};
|
||||
const { altKey, ctrlKey, metaKey, shiftKey } = event;
|
||||
if (mesh.split.active()) {
|
||||
return mesh.split.select(model);
|
||||
|
|
@ -400,21 +412,25 @@ function space_init(data) {
|
|||
} else {
|
||||
selection.toggle(sketch);
|
||||
}
|
||||
} else if (sketch_item) {
|
||||
sketch_item.toggle();
|
||||
}
|
||||
} else {
|
||||
let sketches = api.selection.sketches(true);
|
||||
// return objects upSelect can choose from
|
||||
let visible = api.objects().filter(o => o.visible);
|
||||
let sketches = api.selection.sketches();
|
||||
if (sketches.length) {
|
||||
// when sketch selected, return sketch items, too
|
||||
return sketches[0].object.children;
|
||||
// when sketch selected, append sketch items, too
|
||||
visible.appendAll(sketches[0].object.children);
|
||||
};
|
||||
return api.objects().filter(o => o.visible);
|
||||
return visible;
|
||||
}
|
||||
});
|
||||
|
||||
space.mouse.onDrag((delta, offset, up = false) => {
|
||||
const { mode, modes } = api;
|
||||
if (delta && delta.event.shiftKey) {
|
||||
if (selection.count()) {
|
||||
let { mode, modes } = api;
|
||||
if (delta) {
|
||||
if (delta.event?.shiftKey && selection.count()) {
|
||||
selection.move(delta.x, delta.y, 0);
|
||||
}
|
||||
} else if (up) {
|
||||
|
|
@ -422,7 +438,8 @@ function space_init(data) {
|
|||
selection.drag({ end: true });
|
||||
}
|
||||
} else if (mode.is([ modes.object, modes.tool, modes.sketch ])) {
|
||||
return api.objects().length > 0;
|
||||
// return true if there are draggable elements
|
||||
return api.objects().length > 0 || api.selection.sketches().length;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,10 +49,6 @@ const selection = {
|
|||
return grp;
|
||||
},
|
||||
|
||||
sketches(strict) {
|
||||
return selection.list(strict).filter(s => s.type === 'sketch');
|
||||
},
|
||||
|
||||
// return selected models + models from selected groups
|
||||
models(strict) {
|
||||
let all = selection.list(strict);
|
||||
|
|
@ -66,8 +62,12 @@ const selection = {
|
|||
return mdl;
|
||||
},
|
||||
|
||||
sketches(strict) {
|
||||
return selection.list(strict).filter(s => s.type === 'sketch');
|
||||
sketches() {
|
||||
return selection.list(true).filter(s => s.type === 'sketch');
|
||||
},
|
||||
|
||||
sketch_items() {
|
||||
return selection.list(true).filter(s => s.type === 'sketch_item')
|
||||
},
|
||||
|
||||
contains(object) {
|
||||
|
|
@ -174,6 +174,7 @@ const selection = {
|
|||
|
||||
// update selection and wireframe for all objects
|
||||
update() {
|
||||
// de-select all
|
||||
for (let group of groups) {
|
||||
group.select(false);
|
||||
group.normals(prefs.map.space.norm || false);
|
||||
|
|
|
|||
|
|
@ -126,7 +126,9 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
}
|
||||
|
||||
get meshes() {
|
||||
return this.group.children.filter(c => c.sketch ? c : undefined);
|
||||
return this.group.children.filter(c => {
|
||||
return c.sketch || (c.sketch_item && c.sketch_item.selected) ? c : undefined
|
||||
}).reverse();
|
||||
}
|
||||
|
||||
rename(newname) {
|
||||
|
|
@ -158,6 +160,7 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
for (let handle of handles) {
|
||||
handle.material = bool ? material.highlight : plane.material;
|
||||
}
|
||||
this.render();
|
||||
return bool;
|
||||
}
|
||||
|
||||
|
|
@ -183,6 +186,14 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
scale.y += y * sf[1];
|
||||
scale.z += z * sf[2];
|
||||
this.update();
|
||||
} else if (Array.isArray(dragging)) {
|
||||
for (let item of dragging) {
|
||||
let { center } = item;
|
||||
center.x += x;
|
||||
center.y += y;
|
||||
center.z += z;
|
||||
}
|
||||
this.render();
|
||||
} else {
|
||||
this.center = {x, y, z};
|
||||
this.update();
|
||||
|
|
@ -190,9 +201,10 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
}
|
||||
|
||||
drag(opt = {}) {
|
||||
const { plane, handles, dragging } = this;
|
||||
let { items } = this;
|
||||
if (opt.start) {
|
||||
this.dragging = opt.start;
|
||||
let selected = items.filter(i => i.selected);
|
||||
this.dragging = opt.start.sketch_item ? selected : opt.start;
|
||||
} else if (opt.end) {
|
||||
this.dragging = undefined;
|
||||
} else {
|
||||
|
|
@ -218,44 +230,79 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
render() {
|
||||
let { group } = this;
|
||||
// remove previous item/poly-based children of group
|
||||
group.children.filter(c => c.poly).forEach(c => group.remove(c));
|
||||
group.children.filter(c => c.sketch_item).forEach(c => group.remove(c));
|
||||
// mapy items into polys into meshes to add to group
|
||||
this.items.map(item => {
|
||||
let { type, center, width, height, radius, spacing, poly } = item;
|
||||
if (type === 'circle') {
|
||||
let circumference = 2 * Math.PI * radius;
|
||||
let points = Math.floor(circumference / (spacing || 1));
|
||||
poly = newPolygon().centerCircle(center, radius, points).annotate({ item } );
|
||||
} else if (type === 'rectangle') {
|
||||
poly = newPolygon().centerRectangle(center, width, height).annotate({ item });
|
||||
}
|
||||
return poly;
|
||||
}).filter(o => o).forEach(poly => {
|
||||
let vrt = poly.extrude(0).toFloat32();
|
||||
let geo = new BufferGeometry();
|
||||
geo.setAttribute('position', new BufferAttribute(vrt, 3));
|
||||
let meh = new Mesh(geo, mesh.material.normal);
|
||||
meh.renderOrder = -1;
|
||||
meh.poly = poly;
|
||||
group.add(meh);
|
||||
});
|
||||
for (let si of this.items.map(i => new SketchItem(this, i))) {
|
||||
group.add(si.mesh);
|
||||
}
|
||||
this.update();
|
||||
}
|
||||
|
||||
extrude(opt = {}) {
|
||||
let { z } = opt;
|
||||
let models = [];
|
||||
for (let item of this.group.children.filter(c => c.poly)) {
|
||||
let vert = item.poly.extrude(z || 10);
|
||||
let nmdl = new mesh.model({ file: "poly", mesh: vert.toFloat32() });
|
||||
console.log({ extrude: this });
|
||||
for (let item of this.group.children.filter(c => c.sketch_item)) {
|
||||
let vert = item.sketch_item.extrude(z || 10);
|
||||
let nmdl = new mesh.model({ file: "item", mesh: vert.toFloat32() });
|
||||
models.push(nmdl);
|
||||
}
|
||||
if (models.length) {
|
||||
log('extrude', this.file || this.id, 'into', models.length, 'solid(s)');
|
||||
let { center } = this;
|
||||
let ngrp = api.group.new(models);
|
||||
ngrp.floor();
|
||||
ngrp.move(center.x, center.y, center.z + 0.001);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SketchItem {
|
||||
constructor(sketch, item) {
|
||||
this.sketch = sketch;
|
||||
this.item = item;
|
||||
this.update();
|
||||
}
|
||||
|
||||
get type() {
|
||||
return "sketch_item";
|
||||
}
|
||||
|
||||
get selected() {
|
||||
return this.item.selected;
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.item.selected = !this.item.selected;
|
||||
this.update();
|
||||
this.sketch.render();
|
||||
}
|
||||
|
||||
extrude(opt = {}) {
|
||||
return this.poly.extrude(opt);
|
||||
}
|
||||
|
||||
update() {
|
||||
let { item, sketch } = this;
|
||||
let { material } = mesh;
|
||||
let { type, center, width, height, radius, spacing, poly, selected } = item;
|
||||
if (type === 'circle') {
|
||||
let circumference = 2 * Math.PI * radius;
|
||||
let points = Math.floor(circumference / (spacing || 1));
|
||||
poly = newPolygon().centerCircle(center, radius, points).annotate({ item } );
|
||||
} else if (type === 'rectangle') {
|
||||
poly = newPolygon().centerRectangle(center, width, height).annotate({ item });
|
||||
} else {
|
||||
throw `invalid sketch type: ${type}`;
|
||||
}
|
||||
this.poly = poly;
|
||||
let vrt = poly.extrude(0).toFloat32();
|
||||
let geo = new BufferGeometry();
|
||||
geo.setAttribute('position', new BufferAttribute(vrt, 3));
|
||||
let meh = this.mesh = new Mesh(geo, selected && sketch.select() ? material.select : material.normal);
|
||||
meh.renderOrder = -1;
|
||||
meh.sketch_item = this;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -896,7 +896,7 @@ gapp.register("moto.space", [], (root, exports) => {
|
|||
viewControl.enabled = false;
|
||||
}
|
||||
if (selectInt) {
|
||||
mouseDownSelect(selectInt, event);
|
||||
mouseDownSelect(selectInt, event, int);
|
||||
}
|
||||
if (mouseDown) mouseDown(event, int);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue