add STL export and right-click context menu
This commit is contained in:
parent
328118f628
commit
8acc2cee27
5 changed files with 126 additions and 10 deletions
|
|
@ -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'> 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}> 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() };
|
||||
|
|
|
|||
|
|
@ -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
|
||||
******************************************************************* */
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in a new issue