checkpoint sketch work
This commit is contained in:
parent
c00e4995e6
commit
32e57fd00e
6 changed files with 111 additions and 32 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
tag=${1:-latest}
|
tag=${1:-latest}
|
||||||
./bin/build-upload mac ${tag} && \
|
|
||||||
./bin/build-upload win ${tag} && \
|
./bin/build-upload win ${tag} && \
|
||||||
./bin/build-upload linux ${tag}
|
./bin/build-upload linux ${tag} && \
|
||||||
|
./bin/build-upload mac ${tag}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@
|
||||||
// dep: moto.space
|
// dep: moto.space
|
||||||
// dep: mesh.util
|
// dep: mesh.util
|
||||||
// dep: mesh.edges
|
// dep: mesh.edges
|
||||||
|
// dep: mesh.group
|
||||||
|
// dep: mesh.model
|
||||||
|
// dep: mesh.sketch
|
||||||
// dep: add.three
|
// dep: add.three
|
||||||
// use: add.array
|
// use: add.array
|
||||||
gapp.register("mesh.api", [], (root, exports) => {
|
gapp.register("mesh.api", [], (root, exports) => {
|
||||||
|
|
@ -20,6 +23,7 @@ const { newPolygon } = base;
|
||||||
|
|
||||||
const worker = moto.client.fn
|
const worker = moto.client.fn
|
||||||
const groups = [];
|
const groups = [];
|
||||||
|
const sketches = [];
|
||||||
|
|
||||||
let selected = [];
|
let selected = [];
|
||||||
let tools = [];
|
let tools = [];
|
||||||
|
|
@ -30,7 +34,7 @@ const selection = {
|
||||||
},
|
},
|
||||||
|
|
||||||
// @returns {MeshObject[]} or all groups if not strict and no selection
|
// @returns {MeshObject[]} or all groups if not strict and no selection
|
||||||
list(strict = false) {
|
list(strict) {
|
||||||
return selected.length || strict ? selected.slice() : groups.slice();
|
return selected.length || strict ? selected.slice() : groups.slice();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -156,6 +160,9 @@ const selection = {
|
||||||
opacity: prefs.map.wireframe.opacity}
|
opacity: prefs.map.wireframe.opacity}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
for (let sketch of sketches) {
|
||||||
|
sketch.select(false);
|
||||||
|
}
|
||||||
api.updateFog();
|
api.updateFog();
|
||||||
// prevent selection of model and its group
|
// prevent selection of model and its group
|
||||||
let mgsel = selected.filter(s => s instanceof mesh.model).map(m => m.group);
|
let mgsel = selected.filter(s => s instanceof mesh.model).map(m => m.group);
|
||||||
|
|
@ -377,7 +384,30 @@ let model = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let sketch = {
|
||||||
|
add(sk) {
|
||||||
|
sketches.addOnce(sk);
|
||||||
|
space.world.add(sk.object);
|
||||||
|
api.selection.update();
|
||||||
|
return sk;
|
||||||
|
},
|
||||||
|
|
||||||
|
remove(sk) {
|
||||||
|
sketches.remove(sk);
|
||||||
|
space.world.remove(sk.object);
|
||||||
|
space.update();s
|
||||||
|
},
|
||||||
|
|
||||||
|
list() {
|
||||||
|
return sketches;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let add = {
|
let add = {
|
||||||
|
sketch() {
|
||||||
|
sketch.add(new mesh.sketch());
|
||||||
|
},
|
||||||
|
|
||||||
input() {
|
input() {
|
||||||
api.modal.dialog({
|
api.modal.dialog({
|
||||||
title: "vertices",
|
title: "vertices",
|
||||||
|
|
@ -695,7 +725,7 @@ const tool = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
rename(models) {
|
rename(models, type = 'model') {
|
||||||
models = fallback(models, true);
|
models = fallback(models, true);
|
||||||
let model = models[0];
|
let model = models[0];
|
||||||
if (!model) {
|
if (!model) {
|
||||||
|
|
@ -712,7 +742,7 @@ const tool = {
|
||||||
selection.update();
|
selection.update();
|
||||||
api.modal.hide();
|
api.modal.hide();
|
||||||
};
|
};
|
||||||
let { tempedit } = api.modal.show(`rename model`, h.div({ class: "rename"}, [
|
let { tempedit } = api.modal.show(`rename ${type}`, h.div({ class: "rename"}, [
|
||||||
h.input({ id: "tempedit", value: model.file, onkeydown }),
|
h.input({ id: "tempedit", value: model.file, onkeydown }),
|
||||||
h.button({ _: 'ok', onclick })
|
h.button({ _: 'ok', onclick })
|
||||||
]));
|
]));
|
||||||
|
|
@ -883,28 +913,28 @@ const mode = {
|
||||||
},
|
},
|
||||||
|
|
||||||
object() {
|
object() {
|
||||||
if (mode.is([ modes.face, modes.surface ])) {
|
if (!mode.is([ modes.object, modes.tool ])) {
|
||||||
selection.clear();
|
selection.clear();
|
||||||
}
|
}
|
||||||
mode.set(modes.object);
|
mode.set(modes.object);
|
||||||
},
|
},
|
||||||
|
|
||||||
tool() {
|
tool() {
|
||||||
if (mode.is([ modes.face, modes.surface ])) {
|
if (!mode.is([ modes.object, modes.tool ])) {
|
||||||
selection.clear();
|
selection.clear();
|
||||||
}
|
}
|
||||||
mode.set(modes.tool);
|
mode.set(modes.tool);
|
||||||
},
|
},
|
||||||
|
|
||||||
face() {
|
face() {
|
||||||
if (mode.is([ modes.object, modes.tool ])) {
|
if (!mode.is([ modes.face, modes.surface ])) {
|
||||||
selection.clear();
|
selection.clear();
|
||||||
}
|
}
|
||||||
mode.set(modes.face);
|
mode.set(modes.face);
|
||||||
},
|
},
|
||||||
|
|
||||||
surface() {
|
surface() {
|
||||||
if (mode.is([ modes.object, modes.tool ])) {
|
if (!mode.is([ modes.face, modes.surface ])) {
|
||||||
selection.clear();
|
selection.clear();
|
||||||
}
|
}
|
||||||
mode.set(modes.surface);
|
mode.set(modes.surface);
|
||||||
|
|
@ -1089,6 +1119,8 @@ const api = exports({
|
||||||
|
|
||||||
model,
|
model,
|
||||||
|
|
||||||
|
sketch,
|
||||||
|
|
||||||
add,
|
add,
|
||||||
|
|
||||||
file,
|
file,
|
||||||
|
|
|
||||||
|
|
@ -387,6 +387,8 @@ function ui_build() {
|
||||||
h.button({ _: 'cylinder', onclick() { add.cylinder() } }),
|
h.button({ _: 'cylinder', onclick() { add.cylinder() } }),
|
||||||
h.button({ _: 'cube', onclick() { add.cube() } }),
|
h.button({ _: 'cube', onclick() { add.cube() } }),
|
||||||
h.button({ _: 'gear', onclick() { add.gear() } }),
|
h.button({ _: 'gear', onclick() { add.gear() } }),
|
||||||
|
h.hr(),
|
||||||
|
h.button({ _: 'sketch', onclick() { add.sketch() } }),
|
||||||
devel ? h.button({ _: 'input', onclick: add.input }) : undefined
|
devel ? h.button({ _: 'input', onclick: add.input }) : undefined
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
|
|
@ -488,7 +490,10 @@ function ui_build() {
|
||||||
.map(g => h.div([
|
.map(g => h.div([
|
||||||
h.button({ _: g.name || `group`, title: g.id,
|
h.button({ _: g.name || `group`, title: g.id,
|
||||||
class: [ "group", selHas(g) ? 'selected' : undefined ],
|
class: [ "group", selHas(g) ? 'selected' : undefined ],
|
||||||
onclick(e) { selection.toggle(g) }
|
onclick(e) {
|
||||||
|
api.mode.object();
|
||||||
|
selection.toggle(g);
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
h.div({ class: "models"},
|
h.div({ class: "models"},
|
||||||
// map models to buttons
|
// map models to buttons
|
||||||
|
|
@ -499,18 +504,17 @@ function ui_build() {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
tool.rename([ m ]);
|
tool.rename([ m ]);
|
||||||
} else {
|
} else {
|
||||||
|
if (!api.mode.is([ api.modes.object, api.modes.tool ])) {
|
||||||
|
api.mode.object();
|
||||||
|
}
|
||||||
selection.toggle(m);
|
selection.toggle(m);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onmouseover(e) {
|
onmouseover(e) {
|
||||||
if (!m.wireframe().enabled) {
|
m.highlight();
|
||||||
m.opacity({temp: 0.5});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onmouseleave(e) {
|
onmouseleave(e) {
|
||||||
if (!m.wireframe().enabled) {
|
m.unhighlight();
|
||||||
m.opacity({restore: true});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
h.button({
|
h.button({
|
||||||
|
|
@ -523,6 +527,42 @@ function ui_build() {
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
]));
|
]));
|
||||||
|
let sketches = api.sketch.list();
|
||||||
|
if (sketches.length) {
|
||||||
|
let sg = h.div([
|
||||||
|
h.button({ _: 'sketch',
|
||||||
|
class: [ "group" ],
|
||||||
|
}),
|
||||||
|
sketches.map(sketch => h.div({ class: "models"}, [
|
||||||
|
h.button({ _: sketch.file || sketch.id,
|
||||||
|
class: [ selHas(sketch) ? 'selected' : undefined ],
|
||||||
|
onclick(e) {
|
||||||
|
if (e.shiftKey) {
|
||||||
|
tool.rename([ sketch ], 'sketch');
|
||||||
|
} else {
|
||||||
|
selection.toggle(sketch);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onmouseover(e) {
|
||||||
|
sketch.highlight();
|
||||||
|
},
|
||||||
|
onmouseleave(e) {
|
||||||
|
sketch.unhighlight();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
h.button({
|
||||||
|
class: [ 'square' ],
|
||||||
|
onclick(e) {
|
||||||
|
sketch.visible({ toggle: true });
|
||||||
|
update_selector();
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
h.raw(sketch.visible() ? eye_open : eye_closed)
|
||||||
|
])
|
||||||
|
]))
|
||||||
|
]);
|
||||||
|
groups.push(sg);
|
||||||
|
}
|
||||||
h.bind(grouplist, groups);
|
h.bind(grouplist, groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -564,8 +604,8 @@ function ui_build() {
|
||||||
// update model information dashboard (bottom)
|
// update model information dashboard (bottom)
|
||||||
function update_selection() {
|
function update_selection() {
|
||||||
let map = { fixed: 2 };
|
let map = { fixed: 2 };
|
||||||
let s_grp = selection.groups();
|
let s_grp = selection.groups(true);
|
||||||
let s_mdl = selection.models();
|
let s_mdl = selection.models(true);
|
||||||
if (s_mdl.length === 0) {
|
if (s_mdl.length === 0) {
|
||||||
return h.bind(selectlist, []);
|
return h.bind(selectlist, []);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ let edges = {
|
||||||
},
|
},
|
||||||
|
|
||||||
async add() {
|
async add() {
|
||||||
|
console.log({ add: selected.slice() });
|
||||||
if (selected.length === 2 && selected[0].object === selected[1].object) {
|
if (selected.length === 2 && selected[0].object === selected[1].object) {
|
||||||
let verts = selected.map(s => [ s.side.p0, s.side.p1 ]).flat();
|
let verts = selected.map(s => [ s.side.p0, s.side.p1 ]).flat();
|
||||||
// clean up floating point cruft for comparison
|
// clean up floating point cruft for comparison
|
||||||
|
|
@ -113,7 +114,7 @@ let edges = {
|
||||||
point.z !== arr[index - 1].z;
|
point.z !== arr[index - 1].z;
|
||||||
});
|
});
|
||||||
let model = selected[0].object.model;
|
let model = selected[0].object.model;
|
||||||
if (verts.length === 3) {
|
if (sort.length === 3) {
|
||||||
await model.duplicate({ append: [
|
await model.duplicate({ append: [
|
||||||
sort[0].x, -sort[0].z, sort[0].y,
|
sort[0].x, -sort[0].z, sort[0].y,
|
||||||
sort[1].x, -sort[1].z, sort[1].y,
|
sort[1].x, -sort[1].z, sort[1].y,
|
||||||
|
|
@ -125,8 +126,8 @@ let edges = {
|
||||||
verts[0].x, -verts[0].z, verts[0].y,
|
verts[0].x, -verts[0].z, verts[0].y,
|
||||||
verts[1].x, -verts[1].z, verts[1].y,
|
verts[1].x, -verts[1].z, verts[1].y,
|
||||||
verts[2].x, -verts[2].z, verts[2].y,
|
verts[2].x, -verts[2].z, verts[2].y,
|
||||||
verts[1].x, -verts[1].z, verts[1].y,
|
|
||||||
verts[2].x, -verts[2].z, verts[2].y,
|
verts[2].x, -verts[2].z, verts[2].y,
|
||||||
|
verts[1].x, -verts[1].z, verts[1].y,
|
||||||
verts[3].x, -verts[3].z, verts[3].y,
|
verts[3].x, -verts[3].z, verts[3].y,
|
||||||
]});
|
]});
|
||||||
model.remove();
|
model.remove();
|
||||||
|
|
@ -144,6 +145,7 @@ let edges = {
|
||||||
|
|
||||||
select() {
|
select() {
|
||||||
space.scene.remove(edges.selected);
|
space.scene.remove(edges.selected);
|
||||||
|
if (!hovered) return;
|
||||||
|
|
||||||
const { object, face, side } = hovered;
|
const { object, face, side } = hovered;
|
||||||
let add = true;
|
let add = true;
|
||||||
|
|
|
||||||
|
|
@ -281,17 +281,6 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
return this.vertices / 3;
|
return this.vertices / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get, set, or toggle visibility of model and wireframe
|
|
||||||
visible(bool) {
|
|
||||||
if (bool === undefined) {
|
|
||||||
return this.mesh.visible;
|
|
||||||
}
|
|
||||||
if (bool.toggle) {
|
|
||||||
return this.visible(!this.mesh.visible);
|
|
||||||
}
|
|
||||||
this.mesh.visible = bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get, set, or toggle selection of model (coloring)
|
// get, set, or toggle selection of model (coloring)
|
||||||
select(bool, stool) {
|
select(bool, stool) {
|
||||||
const cmat = this.mesh.material[0];
|
const cmat = this.mesh.material[0];
|
||||||
|
|
@ -344,6 +333,18 @@ mesh.model = class MeshModel extends mesh.object {
|
||||||
space.update();
|
space.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
highlight() {
|
||||||
|
if (!this.wireframe().enabled) {
|
||||||
|
this.opacity({temp: 0.5});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unhighlight() {
|
||||||
|
if (!this.wireframe().enabled) {
|
||||||
|
this.opacity({restore: true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wireframe(bool, opt = {}) {
|
wireframe(bool, opt = {}) {
|
||||||
let was = this._wire ? true : false;
|
let was = this._wire ? true : false;
|
||||||
if (bool === undefined) {
|
if (bool === undefined) {
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,11 @@ mesh.object = class MeshObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
select() {
|
select() {
|
||||||
mesh.api.selection.set([this]);
|
throw "select() requires implementation";
|
||||||
|
}
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
throw "remove() requires implementation";
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue