add sketch z scaling, item ordering, sensible grouping on union
This commit is contained in:
parent
611d3cac1c
commit
a2a5fc1cd4
4 changed files with 119 additions and 26 deletions
|
|
@ -486,7 +486,7 @@ function load_files(files) {
|
|||
return diam ? poly.offset_open(diam / 2, 'round') : null;
|
||||
}).filter(p => p).flat();
|
||||
for (let set of [ closed, open, circs, rects ]) {
|
||||
let group = Date.now().toString(36);
|
||||
let group = mesh.util.uuid();
|
||||
for (let poly of set) {
|
||||
sketch.add.polygon({ poly, group });
|
||||
}
|
||||
|
|
@ -497,7 +497,7 @@ function load_files(files) {
|
|||
if (sketch && has_svg) {
|
||||
load.File.load([...files], { flat: true })
|
||||
.then(polys => polys.forEach(set => {
|
||||
let group = Date.now().toString(36);
|
||||
let group = mesh.util.uuid();
|
||||
set.forEach(poly => sketch.add.polygon({ poly, group }))
|
||||
}))
|
||||
.catch(error => dbug.error(error))
|
||||
|
|
|
|||
|
|
@ -483,16 +483,13 @@ let sketch = {
|
|||
arrange: {
|
||||
group() {
|
||||
sketch.selection.ifcan((sketch, items) => {
|
||||
let group = Date.now().toString(36);
|
||||
items.forEach(i => i.group = group);
|
||||
log('grouped', items.length, 'sketch items');
|
||||
sketch.arrange.group(items);
|
||||
}, 2);
|
||||
},
|
||||
|
||||
ungroup() {
|
||||
sketch.selection.ifcan((sketch, items) => {
|
||||
items.forEach(i => delete i.group);
|
||||
log('ungrouped', items.length, 'sketch items');
|
||||
sketch.arrange.ungroup(items);
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -524,7 +521,35 @@ let sketch = {
|
|||
});
|
||||
sketch.render();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
down() {
|
||||
sketch.selection.ifcan((sketch, items) => {
|
||||
items.forEach(item => sketch.arrange.down(item));
|
||||
sketch.render();
|
||||
});
|
||||
},
|
||||
|
||||
up() {
|
||||
sketch.selection.ifcan((sketch, items) => {
|
||||
items.forEach(item => sketch.arrange.up(item));
|
||||
sketch.render();
|
||||
});
|
||||
},
|
||||
|
||||
top() {
|
||||
sketch.selection.ifcan((sketch, items) => {
|
||||
items.forEach(item => sketch.arrange.top(item));
|
||||
sketch.render();
|
||||
});
|
||||
},
|
||||
|
||||
bottom() {
|
||||
sketch.selection.ifcan((sketch, items) => {
|
||||
items.forEach(item => sketch.arrange.bottom(item));
|
||||
sketch.render();
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
// related to a selected sketch
|
||||
|
|
|
|||
|
|
@ -488,6 +488,12 @@ function ui_build() {
|
|||
h.hr(),
|
||||
h.button({ _: 'flip-h', onclick: sketch.arrange.fliph }),
|
||||
h.button({ _: 'flip-v', onclick: sketch.arrange.flipv }),
|
||||
h.hr(),
|
||||
h.button({ _: 'down', onclick: sketch.arrange.down }),
|
||||
h.button({ _: 'up', onclick: sketch.arrange.up }),
|
||||
h.hr(),
|
||||
h.button({ _: 'top', onclick: sketch.arrange.top }),
|
||||
h.button({ _: 'bottom', onclick: sketch.arrange.bottom }),
|
||||
])
|
||||
]),
|
||||
h.div({ class: "sketch-on" }, [
|
||||
|
|
@ -784,7 +790,7 @@ function ui_build() {
|
|||
let sk_vars = sblock('sketch', sketch.file || sketch.id, grid(
|
||||
util.extract(bounds.center, map),
|
||||
util.extract(bounds.size, map),
|
||||
[ "center", "size" ], und, 'sketch'
|
||||
[ "center", "scale" ], und, 'sketch'
|
||||
));
|
||||
let sel_item;
|
||||
let si_vars = sel.slice(0,1).map(item => item.sketch_item.item).map(item => {
|
||||
|
|
@ -825,7 +831,7 @@ function ui_build() {
|
|||
sketch.center[axis] = nval;
|
||||
sketch.render();
|
||||
}, { sketch: true });
|
||||
let el2 = bound[`sketch_val_${axis.toUpperCase()}_size`];
|
||||
let el2 = bound[`sketch_val_${axis.toUpperCase()}_scale`];
|
||||
el2.classList.add('editable');
|
||||
el2.onclick = field_edit(`${axis} size`, (nval, oval) => {
|
||||
sketch.scale[axis] = nval;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
|
||||
group.add(...handles, outline, plane);
|
||||
|
||||
util.defer(() => this.render());
|
||||
this.render_defer();
|
||||
}
|
||||
|
||||
update() {
|
||||
|
|
@ -205,9 +205,7 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
let polys = items.map(i => i.sketch_item.poly);
|
||||
let union = POLYS.union(polys, 0, true);
|
||||
sketch.selection.delete();
|
||||
for (let poly of union) {
|
||||
sketch.add.polygon({ poly });
|
||||
}
|
||||
sketch.arrange.group(union.map(poly => sketch.add.polygon({ poly })));
|
||||
},
|
||||
|
||||
intersect() {
|
||||
|
|
@ -268,6 +266,57 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
}
|
||||
}
|
||||
|
||||
get arrange() {
|
||||
let sketch = this;
|
||||
let { items } = sketch;
|
||||
return {
|
||||
move(item, target) {
|
||||
let pos = items.indexOf(item);
|
||||
if (pos < 0 || pos >= items.length) {
|
||||
throw new Error('index out of bounds');
|
||||
}
|
||||
if (target === 'top') {
|
||||
let x = items.splice(pos,1);
|
||||
return items.appendAll(x);
|
||||
} else if (target === 'bottom') {
|
||||
let x = items.splice(pos,1);
|
||||
return sketch.items = [...x, ...items];
|
||||
}
|
||||
let newPos = { 'down': pos - 1, 'up': pos + 1 }[target];
|
||||
if (newPos >= 0 && newPos < items.length) {
|
||||
[items[pos], items[newPos]] = [items[newPos], items[pos]];
|
||||
}
|
||||
},
|
||||
|
||||
up(item) {
|
||||
sketch.arrange.move(item, 'up');
|
||||
},
|
||||
|
||||
down(item) {
|
||||
sketch.arrange.move(item, 'down');
|
||||
},
|
||||
|
||||
top(item) {
|
||||
sketch.arrange.move(item, 'top');
|
||||
},
|
||||
|
||||
bottom(item) {
|
||||
sketch.arrange.move(item, 'bottom');
|
||||
},
|
||||
|
||||
group(items) {
|
||||
let group = Date.now().toString(36);
|
||||
items.forEach(i => i.group = group);
|
||||
sketch.render();
|
||||
},
|
||||
|
||||
ungroup(items) {
|
||||
items.forEach(i => i.group = mesh.util.uuid());
|
||||
sketch.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get pattern() {
|
||||
return {
|
||||
circle() {
|
||||
|
|
@ -411,7 +460,7 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
let sketch = this;
|
||||
return {
|
||||
circle(opt = {}) {
|
||||
sketch.add.item({
|
||||
return sketch.add.item({
|
||||
type: "circle",
|
||||
selected: true,
|
||||
...Object.assign({}, { center: {x:0, y:0, z:0}, radius:5 }, opt)
|
||||
|
|
@ -419,7 +468,7 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
},
|
||||
|
||||
rectangle(opt = {}) {
|
||||
sketch.add.polygon({
|
||||
return sketch.add.polygon({
|
||||
...opt,
|
||||
poly: newPolygon().centerRectangle(
|
||||
opt.center || {x:0, y:0, z:0},
|
||||
|
|
@ -433,7 +482,7 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
let poly = opt.poly;
|
||||
delete opt.poly;
|
||||
let { width, miter } = poly._svg || {};
|
||||
sketch.add.item({
|
||||
return sketch.add.item({
|
||||
type: "polygon",
|
||||
width,
|
||||
miter,
|
||||
|
|
@ -444,8 +493,10 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
},
|
||||
|
||||
item(item, opt = {}) {
|
||||
item.group = item.group || mesh.util.uuid();
|
||||
sketch.items.push(item);
|
||||
sketch.render();
|
||||
sketch.render_defer();
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -453,17 +504,27 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
|||
// render items unto the group object
|
||||
render() {
|
||||
let { group } = this;
|
||||
let group_order = {};
|
||||
let group_next = 0;
|
||||
let scale = this.scale.z;
|
||||
// remove previous item/poly-based children of group
|
||||
group.children.filter(c => c.sketch_item || c.sketch_line).forEach(c => group.remove(c));
|
||||
// mapy items into polys into meshes to add to group
|
||||
for (let si of this.items.map((i,o) => new SketchItem(this, i, o))) {
|
||||
group.add(si.mesh);
|
||||
group.add(...si.outs);
|
||||
// map items into polys into meshes to add to group
|
||||
for (let item of this.items) {
|
||||
let order = scale ? (group_order[item.group] ?? group_next++) : group_next++;
|
||||
group_order[item.group] = order;
|
||||
let sketch_item = new SketchItem(this, item, order);
|
||||
group.add(sketch_item.mesh);
|
||||
group.add(...sketch_item.outs);
|
||||
}
|
||||
this.update();
|
||||
space.refresh();
|
||||
}
|
||||
|
||||
render_defer() {
|
||||
util.defer(() => this.render());
|
||||
}
|
||||
|
||||
extrude(opt = {}) {
|
||||
let { selection, height, chamfer, chamfer_top, chamfer_bottom } = opt;
|
||||
let models = [];
|
||||
|
|
@ -533,11 +594,12 @@ class SketchItem {
|
|||
}
|
||||
|
||||
update() {
|
||||
let bump = 0.0025;
|
||||
let { item, sketch, order } = this;
|
||||
let { material } = mesh;
|
||||
let { type, center, width, height, miter, radius, points, spacing, poly, selected } = item;
|
||||
let { open_close, open_width, open_type } = api.prefs.map.sketch;
|
||||
let base = 0.025;
|
||||
let bump = sketch.scale.z || 0.0001;
|
||||
if (type === 'circle') {
|
||||
let circumference = 2 * Math.PI * radius;
|
||||
points = points || Math.floor(circumference / (spacing || 1));
|
||||
|
|
@ -566,7 +628,7 @@ class SketchItem {
|
|||
meh.renderOrder = -1;
|
||||
meh.sketch_item = this;
|
||||
// bump z to avoid z order conflict and ensure item ray intersect priority
|
||||
meh.position.z += bump + (order * bump);
|
||||
meh.position.z += base + (order * bump);
|
||||
// create poly outline(s)
|
||||
let outs = this.outs = [];
|
||||
for (let p of [poly, ...(poly.inner || [])]) {
|
||||
|
|
@ -576,8 +638,8 @@ class SketchItem {
|
|||
let out = new THREE.Line(lge, material.wireline);
|
||||
out.renderOrder = -1;
|
||||
out.sketch_line = this;
|
||||
out.position.z += bump + (order * bump);
|
||||
// out.renderOrder = bump * order;
|
||||
out.position.z += base + (order * bump);
|
||||
out.renderOrder = -10 + (bump * order);
|
||||
outs.push(out);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue