add obj export

This commit is contained in:
Stewart Allen 2021-10-08 21:15:54 -04:00
commit 5b1e2d5eeb
5 changed files with 94 additions and 39 deletions

View file

@ -582,14 +582,14 @@
});
}
function objectsExport() {
function objectsExport(format = "stl") {
// return API.selection.export();
UC.confirm("Export Filename", {ok:true, cancel: false}, "selected.stl").then(name => {
UC.confirm("Export Filename", {ok:true, cancel: false}, `selected.${format}`).then(name => {
if (!name) return;
if (name.toLowerCase().indexOf(".stl") < 0) {
name = `${name}.stl`;
if (name.toLowerCase().indexOf(`.${format}`) < 0) {
name = `${name}.${format}`;
}
API.util.download(API.selection.export(), name);
API.util.download(API.selection.export(format), name);
});
}
@ -1515,6 +1515,11 @@
mesh: () => { UI.tool.show('ft-mesh') },
select: () => { UI.tool.show('ft-select') },
},
mesh: {
name: $('mesh-name'),
points: $('mesh-points'),
faces: $('mesh-faces'),
},
fps: $('fps'),
load: $('load-file'),
@ -2612,9 +2617,11 @@
$('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); };
// mesh buttons
$('mesh-heal').onclick = () => { API.widgets.heal() };
$('mesh-export-stl').onclick = () => { objectsExport('stl') };
$('mesh-export-obj').onclick = () => { objectsExport('obj') };
// context menu
$('context-heal-mesh').onclick = () => { API.widgets.heal() };
$('context-export-stl').onclick = () => { objectsExport() };
$('context-export-workspace').onclick = () => { profileExport(true) };
$('context-clear-workspace').onclick = () => {
API.view.set(VIEWS.ARRANGE);

View file

@ -1593,7 +1593,7 @@
auto_save();
}
function exportSelection() {
function exportSelection(format = "stl") {
let widgets = API.selection.widgets();
if (widgets.length === 0) {
widgets = API.widgets.all();
@ -1606,6 +1606,24 @@
outs.push({geo, widget});
facets += geo.attributes.position.count;
});
if (format === "obj") {
let obj = [];
for (let out of outs) {
let meta = out.widget.meta;
let name = meta.file || 'unnamed';
obj.push(`g ${name}`);
let { position } = out.geo.attributes;
let pvals = position.array;
for (let i=0, il=position.count; i<il; i += 3) {
let pi = i * position.itemSize;
obj.push(`v ${pvals[pi++]} ${pvals[pi++]} ${pvals[pi++]}`);
obj.push(`v ${pvals[pi++]} ${pvals[pi++]} ${pvals[pi++]}`);
obj.push(`v ${pvals[pi++]} ${pvals[pi++]} ${pvals[pi++]}`);
obj.push(`f ${i+1} ${i+2} ${i+3}`);
}
}
return obj.join('\n');
}
let stl = new Uint8Array(80 + 4 + facets * 50);
let dat = new DataView(stl.buffer);
let pos = 84;
@ -1813,11 +1831,7 @@
function platformUpdateSelected() {
let selcount = platform.selected_count();
let extruders = settings.device.extruders;
let menu_show = selcount ? 'flex': '';
$('winfo').style.display = 'none';
if (selcount) {
// UI.scale.classList.add('lt-active');
// UI.rotate.classList.add('lt-active');
UI.nozzle.classList.add('lt-active');
UI.trash.style.display = 'flex';
if (feature.meta && selcount === 1) {
@ -1833,13 +1847,19 @@
if (sp >= 0) {
name = name.substring(sp + 1);
}
$('winfo').style.display = 'flex';
$('winfo').innerHTML = `${UTIL.comma(sel.meta.vertices)}<br>${name}`;
UI.mesh.name.innerText = name;
UI.mesh.points.innerText = sel.meta.vertices;
UI.mesh.faces.innerText = sel.meta.vertices / 3;
}
} else {
UI.mesh.name.innerText = `[${selcount}]`;
UI.mesh.points.innerText = '-';
UI.mesh.faces.innerText = '-';
}
} else {
// UI.scale.classList.remove('lt-active');
// UI.rotate.classList.remove('lt-active');
UI.mesh.name.innerText = '[0]';
UI.mesh.points.innerText = '-';
UI.mesh.faces.innerText = '-';
UI.nozzle.classList.remove('lt-active');
UI.trash.style.display = '';
}

View file

@ -512,6 +512,16 @@ th, tr, td, label {
border-right: 3px solid var(--main-color);
}
#lab-axis, #lab-scale, #lab-size {
border-radius: 3px;
padding: 2px;
border: 1px solid white;
}
#lab-axis:hover, #lab-scale:hover {
background-color: var(--main-color);
color: white;
}
#ft-rotate {
grid-gap: 2px;
grid-template-rows: auto auto auto 1fr;
@ -520,6 +530,17 @@ th, tr, td, label {
#ft-rotate label, #ft-rotate svg {
text-align: center;
}
#ft-rotate svg {
margin-top: 2px;
padding: 1px 15px 1px 15px;
border: 1px solid transparent;
border-radius: 3px;
}
#ft-rotate svg:hover {
border: 1px solid #ccc;
background-color: var(--main-color);
color: white;
}
#ft-rotate > div {
display: flex;
align-items: center;
@ -544,9 +565,21 @@ th, tr, td, label {
margin-left: 0;
margin-right: 0;
}
#ft-mesh label {
font-size: smaller;
}
#ft-mesh .value {
font-family: monospace;
padding-left: 4px;
}
#ft-mesh, #ft-select {
min-width: 200px;
}
#mesh-info {
grid-gap: 2px;
grid-template-rows: auto auto auto;
grid-template-columns: auto 1fr;
}
#lock_x, #lock_y, #lock_z {
position: absolute;
@ -1667,13 +1700,6 @@ th, tr, td, label {
font-size: 12px;
color: #000;
}
#winfo {
position: fixed;
font-size: 10px;
bottom: 5px;
left: 5px;
color: #000;
}
#context-menu {
display: none;
position: absolute;
@ -1701,13 +1727,6 @@ th, tr, td, label {
margin: 5px 0 5px 0;
}
#lab-axis, #lab-scale {
border-radius: 3px;
}
#lab-axis:hover, #lab-scale:hover {
background-color: rgba(0,0,0,0.2);
}
.range-info {
position: relative;
}

View file

@ -110,9 +110,9 @@
</div>
</div>
<div id="ft-scale" class="grow grid">
<div><label>X</label><input id="lock_x" type="checkbox" checked/></div>
<div><label>Y</label><input id="lock_y" type="checkbox" checked/></div>
<div><label>Z</label><input id="lock_z" type="checkbox" checked/></div>
<div><label class="middle">X</label><input id="lock_x" type="checkbox" checked/></div>
<div><label class="middle">Y</label><input id="lock_y" type="checkbox" checked/></div>
<div><label class="middle">Z</label><input id="lock_z" type="checkbox" checked/></div>
<div><label id="lab-axis" lk="axis">axis</label></div>
<div><input id="size_x" size="8" class="value"/></div>
<div><input id="size_y" size="8" class="value"/></div>
@ -124,7 +124,19 @@
<div><label id="lab-scale" lk="scale">scale</label></div>
<button id="scale-reset" class="gr4">reset</button>
</div>
<div id="ft-mesh" class="grow middle">coming soon</div>
<div id="ft-mesh" class="grow f-col">
<div id="mesh-info" class="grid">
<label>object:</label>
<span id="mesh-name" class="value">[0]</span>
<label>points:</label>
<span id="mesh-points" class="value">-</span>
<label>faces:</label>
<span id="mesh-faces" class="value">-</span>
</div>
<button id="mesh-export-obj" lk="rc_xobj">export OBJ</button>
<button id="mesh-export-stl" lk="rc_xstl">export STL</button>
<button id="mesh-heal" lk="rc_heal">heal</button>
</div>
<div id="ft-select" class="grow middle">coming soon</div>
</div>
<div class="footer"></div>
@ -470,14 +482,10 @@
<button id="context-mirror" lk="rc_mirr">mirror</button>
<button id="context-duplicate" lk="rc_dupl">duplicate</button>
<button id="context-setfocus" lk="rc_focs">set focus</button>
<div class="sep"></div>
<button id="context-heal-mesh" lk="rc_heal">heal meshes</button>
<button id="context-export-stl" lk="rc_xstl">export as STL</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>
<div id="winfo" class="noshow"></div>
<div id="alert-area">
<div id="alert-border">
<div id="alert-text">alerts<br>alerts<br>alerts</div>

View file

@ -57,7 +57,8 @@ kiri.lang['en-us'] = {
rc_dupl: "duplicate",
rc_focs: "set focus",
rc_heal: "heal meshes",
rc_xstl: "export as STL",
rc_xobj: "export OBJ",
rc_xstl: "export STL",
// DEVICE MENU and related dialogs
dm_sldt: "select a device type",