fix extrude mesh save issue
This commit is contained in:
parent
5d782cf9a9
commit
132be08553
File diff suppressed because one or more lines are too long
37
src/Scene.js
37
src/Scene.js
@ -24,8 +24,6 @@ window.loader = new THREE.ObjectLoader();
|
|||||||
window.STLexp = new STLExporter();
|
window.STLexp = new STLExporter();
|
||||||
|
|
||||||
window.id = 0
|
window.id = 0
|
||||||
// window.sid = 1
|
|
||||||
// window.mid = 1
|
|
||||||
|
|
||||||
|
|
||||||
const pointMaterial = new THREE.PointsMaterial({
|
const pointMaterial = new THREE.PointsMaterial({
|
||||||
@ -141,7 +139,7 @@ export class Scene {
|
|||||||
|
|
||||||
this.render = render.bind(this);
|
this.render = render.bind(this);
|
||||||
this.addSketch = addSketch.bind(this);
|
this.addSketch = addSketch.bind(this);
|
||||||
this.extrude = extrude.bind(this);
|
this.extrude = this.extrude.bind(this);
|
||||||
this.onHover = onHover.bind(this);
|
this.onHover = onHover.bind(this);
|
||||||
this.onPick = onPick.bind(this);
|
this.onPick = onPick.bind(this);
|
||||||
this.clearSelection = clearSelection.bind(this);
|
this.clearSelection = clearSelection.bind(this);
|
||||||
@ -166,6 +164,8 @@ export class Scene {
|
|||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
resizeCanvas(renderer) {
|
resizeCanvas(renderer) {
|
||||||
const canvas = renderer.domElement;
|
const canvas = renderer.domElement;
|
||||||
const width = canvas.clientWidth;
|
const width = canvas.clientWidth;
|
||||||
@ -185,7 +185,6 @@ export class Scene {
|
|||||||
|
|
||||||
clearScene() {
|
clearScene() {
|
||||||
const deleted = this.obj3d.children.splice(1)
|
const deleted = this.obj3d.children.splice(1)
|
||||||
console.log(deleted)
|
|
||||||
|
|
||||||
for (let i = 0; i < deleted.length; i++) {
|
for (let i = 0; i < deleted.length; i++) {
|
||||||
deleted[i].traverse((obj) => {
|
deleted[i].traverse((obj) => {
|
||||||
@ -195,6 +194,13 @@ export class Scene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newPart() {
|
||||||
|
this.clearScene()
|
||||||
|
window.id = 0
|
||||||
|
this.sid = 1
|
||||||
|
this.mid = 1
|
||||||
|
}
|
||||||
|
|
||||||
loadState(file) { //uglyyy
|
loadState(file) { //uglyyy
|
||||||
|
|
||||||
this.clearScene()
|
this.clearScene()
|
||||||
@ -250,6 +256,21 @@ export class Scene {
|
|||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extrude(sketch, depth) {
|
||||||
|
const mesh = extrude(sketch, depth)
|
||||||
|
mesh.name = 'e' + this.mid++
|
||||||
|
|
||||||
|
this.obj3d.add(mesh)
|
||||||
|
|
||||||
|
this.store.dispatch({ type: 'rx-extrusion', mesh, sketchId: sketch.obj3d.name })
|
||||||
|
|
||||||
|
if (this.activeSketch == sketch) {
|
||||||
|
this.store.dispatch({ type: 'finish-sketch' })
|
||||||
|
sketch.deactivate()
|
||||||
|
}
|
||||||
|
this.render()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
boolOp(m1, m2, op, refresh = false) {
|
boolOp(m1, m2, op, refresh = false) {
|
||||||
let bspA = CSG.fromMesh(m1)
|
let bspA = CSG.fromMesh(m1)
|
||||||
@ -315,26 +336,30 @@ export class Scene {
|
|||||||
let curId
|
let curId
|
||||||
let que = [id]
|
let que = [id]
|
||||||
let idx = 0
|
let idx = 0
|
||||||
|
// let newNodes = {}
|
||||||
|
|
||||||
const { byId, tree } = this.store.getState().treeEntries
|
const { byId, tree } = this.store.getState().treeEntries
|
||||||
while (idx < que.length) {
|
while (idx < que.length) {
|
||||||
curId = que[idx++]
|
curId = que[idx++]
|
||||||
|
|
||||||
if (byId[curId].userData) {
|
if (byId[curId].userData) { // if it is a mesh
|
||||||
const info = byId[curId].userData.featureInfo
|
const info = byId[curId].userData.featureInfo
|
||||||
let newNode
|
let newNode
|
||||||
if (info.length == 2) {
|
if (info.length == 2) {
|
||||||
newNode = this.extrude(byId[info[0]], info[1], true)
|
newNode = extrude(byId[info[0]], info[1])
|
||||||
} else if (info.length == 3) {
|
} else if (info.length == 3) {
|
||||||
newNode = this.boolOp(byId[info[0]], byId[info[1]], info[2], true)
|
newNode = this.boolOp(byId[info[0]], byId[info[1]], info[2], true)
|
||||||
}
|
}
|
||||||
byId[curId].geometry.copy(newNode.geometry)
|
byId[curId].geometry.copy(newNode.geometry)
|
||||||
|
byId[curId].geometry.parameters = newNode.geometry.parameters // took 2 hours to figure out
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let k in tree[curId]) {
|
for (let k in tree[curId]) {
|
||||||
que.push(k)
|
que.push(k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as THREE from '../node_modules/three/src/Three';
|
import * as THREE from '../node_modules/three/src/Three';
|
||||||
import { color } from './shared'
|
import { color } from './shared'
|
||||||
export function extrude(sketch, depth, refresh=false) {
|
export function extrude(sketch, depth) {
|
||||||
|
|
||||||
let constraints = sketch.constraints;
|
let constraints = sketch.constraints;
|
||||||
let linkedObjs = sketch.linkedObjs;
|
let linkedObjs = sketch.linkedObjs;
|
||||||
@ -90,7 +90,6 @@ export function extrude(sketch, depth, refresh=false) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
mesh.name = 'e' + this.mid++
|
|
||||||
mesh.userData.type = 'mesh'
|
mesh.userData.type = 'mesh'
|
||||||
mesh.userData.featureInfo = [sketch.obj3d.name, depth]
|
mesh.userData.featureInfo = [sketch.obj3d.name, depth]
|
||||||
mesh.layers.enable(1)
|
mesh.layers.enable(1)
|
||||||
@ -109,20 +108,8 @@ export function extrude(sketch, depth, refresh=false) {
|
|||||||
mesh.userData.inverted = true
|
mesh.userData.inverted = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mesh
|
||||||
|
|
||||||
if (!refresh) {
|
|
||||||
this.obj3d.add(mesh)
|
|
||||||
|
|
||||||
this.store.dispatch({ type: 'rx-extrusion', mesh, sketchId: sketch.obj3d.name })
|
|
||||||
|
|
||||||
if (this.activeSketch == sketch) {
|
|
||||||
this.store.dispatch({ type: 'finish-sketch' })
|
|
||||||
sketch.deactivate()
|
|
||||||
}
|
|
||||||
this.render()
|
|
||||||
} else {
|
|
||||||
return mesh
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ const link = document.createElement('a');
|
|||||||
link.style.display = 'none';
|
link.style.display = 'none';
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
|
|
||||||
function save(blob, filename) {
|
function saveLegacy(blob, filename) {
|
||||||
|
|
||||||
link.href = URL.createObjectURL(blob);
|
link.href = URL.createObjectURL(blob);
|
||||||
link.download = filename;
|
link.download = filename;
|
||||||
@ -11,24 +11,17 @@ function save(blob, filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function saveArrayBuffer(buffer, filename) {
|
var tzoffset = (new Date()).getTimezoneOffset() * 60000;
|
||||||
|
|
||||||
// save( new Blob( [ buffer ], { type: 'application/octet-stream' } ), filename );
|
|
||||||
save(new Blob([buffer], { type: 'model/stl' }), filename);
|
|
||||||
|
|
||||||
}
|
export function STLExport(filename) {
|
||||||
|
|
||||||
function saveString(text, filename) {
|
|
||||||
|
|
||||||
// save( new Blob( [ text ], { type: 'text/plain' } ), filename );
|
|
||||||
save(new Blob([text], { type: 'application/json' }), filename);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export function STLExport() {
|
|
||||||
if (sc.selected[0] && sc.selected[0].userData.type == 'mesh') {
|
if (sc.selected[0] && sc.selected[0].userData.type == 'mesh') {
|
||||||
|
|
||||||
const result = STLexp.parse(sc.selected[0], { binary: true });
|
const result = STLexp.parse(sc.selected[0], { binary: true });
|
||||||
saveArrayBuffer(result, 'box.stl');
|
|
||||||
|
const time = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -5).replace(/:/g, '-');
|
||||||
|
|
||||||
|
saveLegacy(new Blob([result], { type: 'model/stl' }), `${filename}_${time}.stl`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,25 +86,6 @@ export async function saveFileAs(file, dispatch) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
async function verifyPermission(fileHandle, withWrite) {
|
|
||||||
const opts = {};
|
|
||||||
if (withWrite) {
|
|
||||||
opts.writable = true;
|
|
||||||
// For Chrome 86 and later...
|
|
||||||
opts.mode = 'readwrite';
|
|
||||||
}
|
|
||||||
// Check if we already have permission, if so, return true.
|
|
||||||
if (await fileHandle.queryPermission(opts) === 'granted') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Request permission to the file, if the user grants permission, return true.
|
|
||||||
if (await fileHandle.requestPermission(opts) === 'granted') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// The user did nt grant permission, return false.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export async function openFile(dispatch) {
|
export async function openFile(dispatch) {
|
||||||
// if (!app.confirmDiscard()) {
|
// if (!app.confirmDiscard()) {
|
||||||
@ -135,15 +109,13 @@ export async function openFile(dispatch) {
|
|||||||
if (!fileHandle) {
|
if (!fileHandle) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const file = await fileHandle.getFile();
|
|
||||||
|
|
||||||
readFile(file, fileHandle, dispatch);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const text = await readFile(file);
|
const file = await fileHandle.getFile();
|
||||||
|
const text = await file.text();;
|
||||||
sc.loadState(text)
|
sc.loadState(text)
|
||||||
|
|
||||||
dispatch({ type: 'set-file-handle', fileHandle })
|
dispatch({ type: 'set-file-handle', fileHandle })
|
||||||
// app.setModified(false);
|
// app.setModified(false);
|
||||||
// app.setFocus(true);
|
// app.setFocus(true);
|
@ -10,7 +10,7 @@ import { FaRegFolderOpen, FaFile } from 'react-icons/fa'
|
|||||||
|
|
||||||
import * as Icon from "./icons";
|
import * as Icon from "./icons";
|
||||||
import { Dialog } from './dialog'
|
import { Dialog } from './dialog'
|
||||||
import { STLExport, savePart, saveFile, openFile } from './fileExporter'
|
import { STLExport, saveFile, openFile } from './fileHelpers'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -76,12 +76,25 @@ export const NavBar = () => {
|
|||||||
[Icon.Union, () => boolOp('u'), 'Union'],
|
[Icon.Union, () => boolOp('u'), 'Union'],
|
||||||
[Icon.Subtract, () => boolOp('s'), 'Subtract'],
|
[Icon.Subtract, () => boolOp('s'), 'Subtract'],
|
||||||
[Icon.Intersect, () => boolOp('i'), 'Intersect'],
|
[Icon.Intersect, () => boolOp('i'), 'Intersect'],
|
||||||
[MdInsertDriveFile, savePart, 'New [ctrl+n]'],
|
[MdInsertDriveFile, () => {
|
||||||
[MdSave, () => {
|
sc.newPart()
|
||||||
saveFile(fileHandle, sc.saveScene(), dispatch)
|
dispatch({ type: 'new-part' })
|
||||||
}, 'Save [ctrl+s]'],
|
sc.render()
|
||||||
[MdFolder, () => openFile(dispatch), 'Open'],
|
}, 'New [ctrl+n]'],
|
||||||
[Icon.Stl, STLExport, 'Export STL'],
|
[MdSave,
|
||||||
|
() => {
|
||||||
|
saveFile(fileHandle, sc.saveScene(), dispatch)
|
||||||
|
}
|
||||||
|
, 'Save [ctrl+s]'],
|
||||||
|
[MdFolder, () => {
|
||||||
|
openFile(dispatch).then(
|
||||||
|
()=>sc.render()
|
||||||
|
)
|
||||||
|
}, 'Open'],
|
||||||
|
[Icon.Stl, () => {
|
||||||
|
STLExport('box')
|
||||||
|
},
|
||||||
|
, 'Export STL'],
|
||||||
]
|
]
|
||||||
|
|
||||||
const [_, forceUpdate] = useReducer(x => x + 1, 0);
|
const [_, forceUpdate] = useReducer(x => x + 1, 0);
|
||||||
|
@ -97,9 +97,10 @@ export function treeEntries(state = defaultState, action) {
|
|||||||
const depTree = new DepTree(state)
|
const depTree = new DepTree(state)
|
||||||
const obj = depTree.deleteNode(action.id)
|
const obj = depTree.deleteNode(action.id)
|
||||||
return update(state, { $merge: obj })
|
return update(state, { $merge: obj })
|
||||||
|
|
||||||
case 'restore-state':
|
case 'restore-state':
|
||||||
return action.state
|
return action.state
|
||||||
|
case 'new-part':
|
||||||
|
return defaultState
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
@ -121,6 +122,11 @@ export function ui(state = { dialog: {}, filePane: false }, action) {
|
|||||||
fileHandle: { $set: action.fileHandle },
|
fileHandle: { $set: action.fileHandle },
|
||||||
modified: { $set: false },
|
modified: { $set: false },
|
||||||
})
|
})
|
||||||
|
case 'new-part':
|
||||||
|
return update(state, {
|
||||||
|
fileHandle: { $set: null },
|
||||||
|
modified: { $set: false },
|
||||||
|
})
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user