add STL export and right-click context menu

This commit is contained in:
Stewart Allen 2020-12-06 21:25:31 -05:00
commit 8acc2cee27
5 changed files with 126 additions and 10 deletions

View file

@ -554,19 +554,38 @@
});
}
function profileExport() {
function objectsExport() {
// return API.selection.export();
UC.confirm("Export Filename", {ok:true, cancel: false}, "selected.stl").then(name => {
if (!name) return;
if (name.toLowerCase().indexOf(".stl") < 0) {
name = `${name}.stl`;
}
let xprt = API.selection.export(),
blob = new Blob([xprt], {type: "octet/stream"}),
url = WIN.URL.createObjectURL(blob);
$('mod-any').innerHTML = [
`<a id="sexport" href="${url}" download="${name}">x</a>`
].join('');
$('sexport').click();
});
}
function profileExport(workspace) {
let checked = workspace ? ' checked' : '';
const opt = {pre: [
"<div class='f-col a-center'>",
" <h3>Profile Export</h3>",
` <h3>${workspace ? "Workspace" : "Profile"} Export</h3>`,
" <label>This will create a backup of</label>",
" <label>your device profiles and settings</label>",
" <br>",
" <div class='f-row'>",
" <input id='incwork' type='checkbox'>&nbsp;include workspace",
workspace ?
" <label>your workspace and settings</label>" :
" <label>your device profiles and settings</label><br>",
` <div class='f-row' style="display:${workspace ? 'none' : ''}">`,
` <input id='incwork' type='checkbox'${checked}>&nbsp;include workspace`,
" </div>",
"</div>"
]};
UC.confirm("Export Filename", {ok:true, cancel: false}, "profile", opt).then(name => {
UC.confirm("Export Filename", {ok:true, cancel: false}, "workspace", opt).then(name => {
if (name) {
let work = $('incwork').checked,
json = API.conf.export({work}),
@ -1354,7 +1373,7 @@
slice: $('label-slice'),
preview: $('label-preview'),
animate: $('label-animate'),
export: $('label-export')
export: $('label-export'),
},
acct: {
@ -1366,6 +1385,7 @@
load: $('load-file'),
speeds: $('speeds'),
speedbar: $('speedbar'),
context: $('context-menu'),
container: container,
back: $('lt-back'),
@ -2031,6 +2051,18 @@
if (int) API.event.emit('mouse.hover', {point: int, event, type: 'platform'});
});
SPACE.mouse.up((event, int) => {
if (event.button === 2 && API.view.isArrange()) {
let style = UI.context.style;
style.display = 'flex';
style.left = `${event.clientX-3}px`;
style.top = `${event.clientY-3}px`;
UI.context.onmouseleave = () => {
style.display = '';
};
}
});
SPACE.mouse.downSelect((int,event) => {
if (API.feature.hover) {
if (int) {
@ -2299,6 +2331,10 @@
$('render-ghost').onclick = () => { API.view.wireframe(false, 0, 0.5); };
$('render-wire').onclick = () => { API.view.wireframe(true, 0, 0.5); };
$('render-solid').onclick = () => { API.view.wireframe(false, 0, 1); };
// context menu
$('context-export-stl').onclick = () => { objectsExport() };
$('context-export-workspace').onclick = () => { profileExport(true) };
$('context-clear-workspace').onclick = () => { API.platform.clear(); UI.context.onmouseleave() };
UI.modal.onclick = API.modal.hide;
UI.modalBox.onclick = (ev) => { ev.stopPropagation() };

View file

@ -87,7 +87,8 @@
for_groups: forSelectedGroups,
for_meshes: forSelectedMeshes,
for_widgets: forSelectedWidgets,
delete: function() { platform.delete(selection.widgets()) }
delete: function() { platform.delete(selection.widgets()) },
export: exportSelection
};
const platform = {
@ -320,7 +321,8 @@
update_fields: updateFields,
wireframe: setWireframe,
snapshot: null,
unit_scale: unitScale
unit_scale: unitScale,
isArrange: function() { return viewMode === VIEWS.ARRANGE }
},
widgets: {
map: function() {
@ -1131,6 +1133,52 @@
auto_save();
}
function exportSelection() {
let widgets = API.selection.widgets();
if (widgets.length === 0) {
widgets = API.widgets.all();
}
let facets = 0;
let outs = [];
widgets.forEach(widget => {
let mesh = widget.mesh;
let geo = new THREE.Geometry().fromBufferGeometry(mesh.geometry);
outs.push({geo, widget});
facets += geo.faces.length;
});
let stl = new Uint8Array(80 + 4 + facets * 50);
let dat = new DataView(stl.buffer);
let pos = 84;
dat.setInt32(80, facets, true);
outs.forEach(out => {
let { faces, vertices } = out.geo;
for (let i=0, il=faces.length; i<il; i++) {
let {a, b, c, normal} = faces[i];
let xo = 0, yo = 0, zo = 0;
if (outs.length > 1) {
let {x, y, z} = out.widget.track.pos;
xo = x;
yo = y;
zo = z;
}
dat.setFloat32(pos + 0, normal.x, true);
dat.setFloat32(pos + 4, normal.y, true);
dat.setFloat32(pos + 8, normal.z, true);
dat.setFloat32(pos + 12, vertices[a].x + xo, true);
dat.setFloat32(pos + 16, vertices[a].y + yo, true);
dat.setFloat32(pos + 20, vertices[a].z + zo, true);
dat.setFloat32(pos + 24, vertices[b].x + xo, true);
dat.setFloat32(pos + 28, vertices[b].y + yo, true);
dat.setFloat32(pos + 32, vertices[b].z + zo, true);
dat.setFloat32(pos + 36, vertices[c].x + xo, true);
dat.setFloat32(pos + 40, vertices[c].y + yo, true);
dat.setFloat32(pos + 44, vertices[c].z + zo, true);
pos += 50;
}
});
return stl;
}
/** ******************************************************************
* Platform Functions
******************************************************************* */

View file

@ -42,6 +42,8 @@
mouseDragStart = null,
mouseDownSelect,
mouseUpSelect,
mouseUp,
mouseDown,
mouseHover,
mouseDrag,
gridOrigin,
@ -648,7 +650,11 @@
if (selectInt) {
mouseDownSelect(selectInt, event);
}
if (mouseDown) mouseDown(event, int);
}
} else if (mouseDown) {
let int = intersect(selection.slice().append(platform), false);
if (int && int.length) mouseDown(event, int);
}
if (platformClick) {
let vis = platform.visible;
@ -682,6 +688,16 @@
if (mouseUpSelect) selection = mouseUpSelect();
if (selection && selection.length > 0) {
let int = intersect(selection, selectRecurse);
if (mouseUp) {
if (int.length) {
mouseUp(event, int);
} else {
mouseUp(event, intersect([platform], selectRecurse));
}
if (event.button === 2) {
return;
}
}
if (int.length > 0) {
mouseUpSelect(int[0], event);
refresh = true;
@ -865,6 +881,8 @@
},
mouse: {
up: function(f) { mouseUp = f },
down: function(f) { mouseDown = f },
downSelect: function(f) { mouseDownSelect = f },
upSelect: function(f) { mouseUpSelect = f },
onDrag: function(f) { mouseDrag = f },

View file

@ -1218,3 +1218,12 @@ th, tr, td, label {
left: 5px;
color: #000;
}
#context-menu {
display: none;
position: absolute;
flex-direction: column;
padding: 4px !important;
border: 1px solid #999;
border-radius: 3px;
background-color: rgba(255,255,255,0.75);
}

View file

@ -395,6 +395,11 @@
<button id="gotit" class="f-col j-center">got it</button>
</div>
<div id="tool-info" class="noshow"></div>
<div id="context-menu">
<button id="context-export-stl">export selection as STL</button>
<button id="context-export-workspace">export workspace</button>
<button id="context-clear-workspace">clear workspace</button>
</div>
<div id="fps" class="noshow"></div>
<div id="layer-animate" class="f-col a-center"></div>
<div id="layer-toolpos" class="f-row a-center"></div>