add sketch item(s) duplication
This commit is contained in:
parent
e0d449af50
commit
a6c4f8aff1
3 changed files with 81 additions and 50 deletions
|
|
@ -378,7 +378,7 @@ function space_init(data) {
|
||||||
const normal = shiftKey ? int.face.normal.applyQuaternion(q) : undefined;
|
const normal = shiftKey ? int.face.normal.applyQuaternion(q) : undefined;
|
||||||
// y,z swap due to world rotation for orbit controls
|
// y,z swap due to world rotation for orbit controls
|
||||||
api.focus({center: { x, y:-z, z:y }, normal});
|
api.focus({center: { x, y:-z, z:y }, normal});
|
||||||
let one = api.sketch.selection.one;
|
let one = api.sketch.selected.one;
|
||||||
if (one && confirm('attach sketch to face?')) {
|
if (one && confirm('attach sketch to face?')) {
|
||||||
one.center = {
|
one.center = {
|
||||||
x, y: -z, z: y
|
x, y: -z, z: y
|
||||||
|
|
@ -471,7 +471,7 @@ function load_files(files) {
|
||||||
let has_image = false;
|
let has_image = false;
|
||||||
let has_svg = false;
|
let has_svg = false;
|
||||||
let has_gbr = false;
|
let has_gbr = false;
|
||||||
let sketch = api.sketch.selection.one;
|
let sketch = api.sketch.selected.one;
|
||||||
for (let file of files) {
|
for (let file of files) {
|
||||||
has_image = has_image || file.type === 'image/png';
|
has_image = has_image || file.type === 'image/png';
|
||||||
has_svg = has_svg || file.name.toLowerCase().endsWith(".svg") > 0;
|
has_svg = has_svg || file.name.toLowerCase().endsWith(".svg") > 0;
|
||||||
|
|
|
||||||
114
src/mesh/api.js
114
src/mesh/api.js
|
|
@ -134,7 +134,7 @@ const selection = {
|
||||||
|
|
||||||
// remove all
|
// remove all
|
||||||
delete() {
|
delete() {
|
||||||
if (sketch.selection.delete()) {
|
if (sketch.selected.delete()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let s of selection.list()) {
|
for (let s of selection.list()) {
|
||||||
|
|
@ -163,7 +163,7 @@ const selection = {
|
||||||
},
|
},
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
if (sketch.selection.clear()) {
|
if (sketch.selected.clear()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let s of selection.list()) {
|
for (let s of selection.list()) {
|
||||||
|
|
@ -466,7 +466,7 @@ let sketch = {
|
||||||
h.button({ _: "create", onclick() {
|
h.button({ _: "create", onclick() {
|
||||||
const { _height, _chamtop, _chambot } = api.modal.bound;
|
const { _height, _chamtop, _chambot } = api.modal.bound;
|
||||||
sketch.extrude({
|
sketch.extrude({
|
||||||
selection: sketch.selection.count() > 0,
|
selection: sketch.selected.count() > 0,
|
||||||
...opt,
|
...opt,
|
||||||
height: parseFloat(_height.value),
|
height: parseFloat(_height.value),
|
||||||
chamfer_top: parseFloat(_chamtop.value),
|
chamfer_top: parseFloat(_chamtop.value),
|
||||||
|
|
@ -480,32 +480,23 @@ let sketch = {
|
||||||
},
|
},
|
||||||
|
|
||||||
arrange: {
|
arrange: {
|
||||||
ifcan(fn, count = 1) {
|
|
||||||
let one = sketch.selection.one;
|
|
||||||
let items = one?.items.filter(i => i.selected);
|
|
||||||
(items.length >= count) && fn(one, items);
|
|
||||||
},
|
|
||||||
|
|
||||||
group() {
|
group() {
|
||||||
let one = sketch.selection.one;
|
sketch.selection.ifcan((sketch, items) => {
|
||||||
let items = one?.items.filter(i => i.selected);
|
|
||||||
if (items.length > 1) {
|
|
||||||
let group = Date.now().toString(36);
|
let group = Date.now().toString(36);
|
||||||
items.forEach(i => i.group = group);
|
items.forEach(i => i.group = group);
|
||||||
log('grouped', items.length, 'sketch items');
|
log('grouped', items.length, 'sketch items');
|
||||||
}
|
}, 2);
|
||||||
|
},
|
||||||
|
|
||||||
|
ungroup() {
|
||||||
|
sketch.selection.ifcan((sketch, items) => {
|
||||||
|
items.forEach(i => delete i.group);
|
||||||
|
log('ungrouped', items.length, 'sketch items');
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
center() {
|
center() {
|
||||||
sketch.arrange.ifcan((sketch, items) => {
|
sketch.selection.bounded_op((sketch, bounds, recs) => {
|
||||||
let bounds;
|
|
||||||
let recs = [];
|
|
||||||
items.filter(i => i.type === 'polygon').forEach(item => {
|
|
||||||
let poly = newPolygon().fromObject(item);
|
|
||||||
let bnds = poly.bounds;
|
|
||||||
bounds = (bounds ? bounds.merge(bnds) : bnds);
|
|
||||||
recs.push({ item, poly });
|
|
||||||
});
|
|
||||||
let center = bounds.center(0);
|
let center = bounds.center(0);
|
||||||
for (let rec of recs) {
|
for (let rec of recs) {
|
||||||
rec.poly.move({ x: -center.x, y: -center.y, z:0 });
|
rec.poly.move({ x: -center.x, y: -center.y, z:0 });
|
||||||
|
|
@ -515,17 +506,8 @@ let sketch = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
ungroup() {
|
|
||||||
let one = sketch.selection.one;
|
|
||||||
let items = one?.items.filter(i => i.selected)
|
|
||||||
if (items.length > 1) {
|
|
||||||
items.forEach(i => delete i.group);
|
|
||||||
log('ungrouped', items.length, 'sketch items');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
fliph() {
|
fliph() {
|
||||||
sketch.arrange.ifcan((sketch, items) => {
|
sketch.selection.ifcan((sketch, items) => {
|
||||||
items.filter(i => i.type === 'polygon').forEach(item => {
|
items.filter(i => i.type === 'polygon').forEach(item => {
|
||||||
Object.assign(item, newPolygon().fromObject(item).flip('x').toObject());
|
Object.assign(item, newPolygon().fromObject(item).flip('x').toObject());
|
||||||
});
|
});
|
||||||
|
|
@ -534,7 +516,7 @@ let sketch = {
|
||||||
},
|
},
|
||||||
|
|
||||||
flipv() {
|
flipv() {
|
||||||
sketch.arrange.ifcan((sketch, items) => {
|
sketch.selection.ifcan((sketch, items) => {
|
||||||
items.filter(i => i.type === 'polygon').forEach(item => {
|
items.filter(i => i.type === 'polygon').forEach(item => {
|
||||||
Object.assign(item, newPolygon().fromObject(item).flip('y').toObject());
|
Object.assign(item, newPolygon().fromObject(item).flip('y').toObject());
|
||||||
});
|
});
|
||||||
|
|
@ -543,7 +525,8 @@ let sketch = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
selection: {
|
// related to a selected sketch
|
||||||
|
selected: {
|
||||||
get one() {
|
get one() {
|
||||||
return selection.sketch();
|
return selection.sketch();
|
||||||
},
|
},
|
||||||
|
|
@ -560,42 +543,84 @@ let sketch = {
|
||||||
delete() {
|
delete() {
|
||||||
let list = selection.list(true);
|
let list = selection.list(true);
|
||||||
return list[0]?.type === 'sketch' && list[0].selection.delete();
|
return list[0]?.type === 'sketch' && list[0].selection.delete();
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// related to items selections in a selected sketch
|
||||||
|
selection: {
|
||||||
|
ifcan(fn, count = 1) {
|
||||||
|
let one = sketch.selected.one;
|
||||||
|
let items = one?.items.filter(i => i.selected);
|
||||||
|
if (items?.length >= count) {
|
||||||
|
return fn(one, items) || true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
bounded_op(fn) {
|
||||||
|
return sketch.selection.ifcan((sketch, items) => {
|
||||||
|
let bounds;
|
||||||
|
let recs = [];
|
||||||
|
items.filter(i => i.type === 'polygon').forEach(item => {
|
||||||
|
let poly = newPolygon().fromObject(item);
|
||||||
|
let bnds = poly.bounds;
|
||||||
|
bounds = (bounds ? bounds.merge(bnds) : bnds);
|
||||||
|
recs.push({ item, poly });
|
||||||
|
});
|
||||||
|
return (bounds && (fn(sketch, bounds, recs) || true)) || false;
|
||||||
|
}) || false;
|
||||||
|
},
|
||||||
|
|
||||||
|
duplicate(opt = {}) {
|
||||||
|
return sketch.selection.bounded_op((sketch, bounds, recs) => {
|
||||||
|
let { shift, select } = opt;
|
||||||
|
let x = bounds.width(), y = 0, z = 0;
|
||||||
|
for (let rec of recs) {
|
||||||
|
let { item, poly } = rec;
|
||||||
|
let item2 = structuredClone(item);
|
||||||
|
item.selected = !select;
|
||||||
|
item2.group += 'D';
|
||||||
|
shift && Object.assign(item2, poly.move({ x, y, z }).toObject());
|
||||||
|
sketch.add_item(item2, { select });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
boolean: {
|
boolean: {
|
||||||
nest() {
|
nest() {
|
||||||
sketch.selection.one?.boolean.nest();
|
sketch.selected.one?.boolean.nest();
|
||||||
},
|
},
|
||||||
|
|
||||||
flatten() {
|
flatten() {
|
||||||
sketch.selection.one?.boolean.flatten();
|
sketch.selected.one?.boolean.flatten();
|
||||||
},
|
},
|
||||||
|
|
||||||
evenodd() {
|
evenodd() {
|
||||||
sketch.selection.one?.boolean.evenodd();
|
sketch.selected.one?.boolean.evenodd();
|
||||||
},
|
},
|
||||||
|
|
||||||
union() {
|
union() {
|
||||||
sketch.selection.one?.boolean.union();
|
sketch.selected.one?.boolean.union();
|
||||||
},
|
},
|
||||||
|
|
||||||
intersect() {
|
intersect() {
|
||||||
sketch.selection.one?.boolean.intersect();
|
sketch.selected.one?.boolean.intersect();
|
||||||
},
|
},
|
||||||
|
|
||||||
difference() {
|
difference() {
|
||||||
sketch.selection.one?.boolean.difference();
|
sketch.selected.one?.boolean.difference();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
pattern: {
|
pattern: {
|
||||||
circle() {
|
circle() {
|
||||||
sketch.selection.one?.pattern.circle();
|
sketch.selected.one?.pattern.circle();
|
||||||
},
|
},
|
||||||
|
|
||||||
grid() {
|
grid() {
|
||||||
sketch.selection.one?.pattern.grid();
|
sketch.selected.one?.pattern.grid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -952,6 +977,9 @@ const tool = {
|
||||||
|
|
||||||
duplicate() {
|
duplicate() {
|
||||||
let { dup_shift, dup_sel } = api.prefs.map.space;
|
let { dup_shift, dup_sel } = api.prefs.map.space;
|
||||||
|
if (sketch.selection.duplicate({ select: dup_sel, shift: dup_shift })) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let models = selection.models();
|
let models = selection.models();
|
||||||
if (dup_sel) {
|
if (dup_sel) {
|
||||||
selection.clear();
|
selection.clear();
|
||||||
|
|
|
||||||
|
|
@ -405,34 +405,37 @@ mesh.sketch = class MeshSketch extends mesh.object {
|
||||||
|
|
||||||
add_circle(opt = {}) {
|
add_circle(opt = {}) {
|
||||||
log(this.file || this.id, '| add circle');
|
log(this.file || this.id, '| add circle');
|
||||||
this.items.push({
|
this.add_item({
|
||||||
type: "circle",
|
type: "circle",
|
||||||
selected: true,
|
selected: true,
|
||||||
...Object.assign({}, { center: {x:0, y:0, z:0}, radius:5 }, opt)
|
...Object.assign({}, { center: {x:0, y:0, z:0}, radius:5 }, opt)
|
||||||
});
|
});
|
||||||
this.render();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add_rectangle(opt = {}) {
|
add_rectangle(opt = {}) {
|
||||||
log(this.file || this.id, '| add rectangle');
|
log(this.file || this.id, '| add rectangle');
|
||||||
this.items.push({
|
this.add_item({
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
selected: true,
|
selected: true,
|
||||||
...Object.assign({}, { center: {x:0, y:0, z:0}, width:15, height:10 }, opt)
|
...Object.assign({}, { center: {x:0, y:0, z:0}, width:15, height:10 }, opt)
|
||||||
});
|
});
|
||||||
this.render();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add_polygon(opt = {}) {
|
add_polygon(opt = {}) {
|
||||||
// log(this.file || this.id, '| add polygon');
|
// log(this.file || this.id, '| add polygon');
|
||||||
let poly = opt.poly;
|
let poly = opt.poly;
|
||||||
delete opt.poly;
|
delete opt.poly;
|
||||||
this.items.push({
|
this.add_item({
|
||||||
type: "polygon",
|
type: "polygon",
|
||||||
selected: true,
|
selected: true,
|
||||||
...Object.assign({}, { center: {x:0, y:0, z:0} }, opt),
|
...Object.assign({}, { center: {x:0, y:0, z:0} }, opt),
|
||||||
...poly.toObject()
|
...poly.toObject()
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
add_item(item, opt = {}) {
|
||||||
|
item.selected = opt.select || false;
|
||||||
|
this.items.push(item);
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue