implement dynamic import correctly

master
howard 2021-04-23 13:13:49 -07:00
parent cef6ae23fd
commit b73aa098a5
16 changed files with 235 additions and 97 deletions

108
package-lock.json generated
View File

@ -9,6 +9,7 @@
"@tailwindcss/jit": "^0.1.18", "@tailwindcss/jit": "^0.1.18",
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"browser-fs-access": "^0.16.4", "browser-fs-access": "^0.16.4",
"bson": "^4.3.0",
"copy-webpack-plugin": "^8.1.1", "copy-webpack-plugin": "^8.1.1",
"css-loader": "^5.1.3", "css-loader": "^5.1.3",
"gh-pages": "^3.1.0", "gh-pages": "^3.1.0",
@ -1284,6 +1285,26 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/batch": { "node_modules/batch": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@ -1428,6 +1449,42 @@
"url": "https://opencollective.com/browserslist" "url": "https://opencollective.com/browserslist"
} }
}, },
"node_modules/bson": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.3.0.tgz",
"integrity": "sha512-LkKKeFJx5D6RRCRvLE+fDs40M2ZQNuk7W7tFXmKd7OOcQQ+BHdzCgRdL4XEGjc1UEGtiYuMvIVk91Bv8qsI50A==",
"dev": true,
"dependencies": {
"buffer": "^5.6.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/buffer-from": { "node_modules/buffer-from": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@ -3708,6 +3765,26 @@
"postcss": "^8.1.0" "postcss": "^8.1.0"
} }
}, },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.1.8", "version": "5.1.8",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
@ -9601,6 +9678,12 @@
} }
} }
}, },
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true
},
"batch": { "batch": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@ -9722,6 +9805,25 @@
"node-releases": "^1.1.70" "node-releases": "^1.1.70"
} }
}, },
"bson": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.3.0.tgz",
"integrity": "sha512-LkKKeFJx5D6RRCRvLE+fDs40M2ZQNuk7W7tFXmKd7OOcQQ+BHdzCgRdL4XEGjc1UEGtiYuMvIVk91Bv8qsI50A==",
"dev": true,
"requires": {
"buffer": "^5.6.0"
}
},
"buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"dev": true,
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"buffer-from": { "buffer-from": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@ -11557,6 +11659,12 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true
},
"ignore": { "ignore": {
"version": "5.1.8", "version": "5.1.8",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",

View File

@ -10,6 +10,7 @@
"@tailwindcss/jit": "^0.1.18", "@tailwindcss/jit": "^0.1.18",
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"browser-fs-access": "^0.16.4", "browser-fs-access": "^0.16.4",
"bson": "^4.3.0",
"copy-webpack-plugin": "^8.1.1", "copy-webpack-plugin": "^8.1.1",
"css-loader": "^5.1.3", "css-loader": "^5.1.3",
"gh-pages": "^3.1.0", "gh-pages": "^3.1.0",

View File

@ -417,4 +417,4 @@ function addSketch() {
return sketch return sketch
} }
window.sc = new Scene(store) // window.sc = new Scene(store)

View File

@ -155,7 +155,7 @@ export async function drawDimension() {
} }
) )
this.labelContainer.removeChild(this.labelContainer.lastChild); this.labelContainer.removeChild(this.labelContainer.lastChild);
sc.render() this.scene.render()
} }
if (this.mode == "dimension") { if (this.mode == "dimension") {
this.drawDimension() this.drawDimension()
@ -176,7 +176,7 @@ export function updateDim(c_id) {
this.constraints.set(c_id, ent) this.constraints.set(c_id, ent)
this.updateOtherBuffers() this.updateOtherBuffers()
this.solve() this.solve()
sc.render() this.scene.render()
ev_focus.target.blur() ev_focus.target.blur()
this.updateBoundingSpheres() this.updateBoundingSpheres()
} else if (e.key == 'Escape') { } else if (e.key == 'Escape') {
@ -217,7 +217,7 @@ export function _onMoveDimension(point, line, initial) {
point, point,
_p1, _p2, null, initial _p1, _p2, null, initial
) )
sc.render() this.scene.render()
} }
} }

View File

@ -78,7 +78,7 @@ export function drawPreClick2(e) {
} }
sc.render() this.scene.render()
} }
export function drawOnClick2(e) { export function drawOnClick2(e) {
@ -136,7 +136,7 @@ let ccw;
export function drawPreClick3(e) { export function drawPreClick3(e) {
const mouseLoc = this.getLocation(e); const mouseLoc = this.getLocation(e);
ccw = drawArc4(mouseLoc, this.toPush) ccw = drawArc4(mouseLoc, this.toPush)
sc.render() this.scene.render()
} }
export function drawOnClick3(e) { export function drawOnClick3(e) {

View File

@ -219,7 +219,8 @@ export function onPick(e) {
} }
// dont think this would have been possible without redux // dont think this would have been possible without redux
if (obj.userData.type == 'sketch' && !sc.store.getState().treeEntries.visible[obj.name]) { // if (obj.userData.type == 'sketch' && !sc.store.getState().treeEntries.visible[obj.name]) {
if (obj.userData.type == 'sketch' && !this.scene.store.getState().treeEntries.visible[obj.name]) {
obj.visible = false obj.visible = false
} }

View File

@ -11,8 +11,13 @@ import { ToolTip } from './toolTip'
import './app.css' import './app.css'
// export async function serial(...args) {
// return (await import('bson')).serialize(...args);
// }
// export async function deserial(...args) {
// return (await import('bson')).deserialize(...args);
// }
let store let store
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
@ -22,6 +27,7 @@ if (process.env.NODE_ENV === 'production') {
store = createStore(reducer, {}, applyMiddleware(logger)) store = createStore(reducer, {}, applyMiddleware(logger))
} }
const App = ({ store }) => { const App = ({ store }) => {
return <Provider store={store}> return <Provider store={store}>
<NavBar /> <NavBar />
@ -30,8 +36,15 @@ const App = ({ store }) => {
</Provider> </Provider>
} }
document.addEventListener('DOMContentLoaded', () => { export let sce
document.addEventListener('DOMContentLoaded', async () => {
const { Scene } = await import('../Scene')
sce = new Scene(store)
// window.sc = sce
ReactDOM.render(<App store={store} />, document.getElementById('react')); ReactDOM.render(<App store={store} />, document.getElementById('react'));
}); });
window.store = store // window.store = store

View File

@ -1,3 +1,4 @@
import {sce} from './app'
export class DepTree { export class DepTree {
constructor(obj) { constructor(obj) {
@ -64,7 +65,8 @@ export class DepTree {
this.allIds.splice(spliceIdx, 1) this.allIds.splice(spliceIdx, 1)
const deletedObj = sc.obj3d.children.splice(spliceIdx + 1, 1)[0] // first 1 elements are non geom // const deletedObj = sc.obj3d.children.splice(spliceIdx + 1, 1)[0] // first 1 elements are non geom
const deletedObj = sce.obj3d.children.splice(spliceIdx + 1, 1)[0] // first 1 elements are non geom
deletedObj.traverse((obj) => { deletedObj.traverse((obj) => {
if (obj.geometry) obj.geometry.dispose() if (obj.geometry) obj.geometry.dispose()

View File

@ -6,6 +6,8 @@ import { useDispatch, useSelector } from 'react-redux'
import { MdDone, MdClose } from 'react-icons/md' import { MdDone, MdClose } from 'react-icons/md'
import * as Icon from "./icons"; import * as Icon from "./icons";
import {sce} from './app'
export const Dialog = () => { export const Dialog = () => {
@ -21,22 +23,22 @@ export const Dialog = () => {
}, [dialog]) }, [dialog])
const extrude = () => { const extrude = () => {
const mesh = sc.extrude(dialog.target, ref.current.value) const mesh = sce.extrude(dialog.target, ref.current.value)
dispatch({ type: 'rx-extrusion', mesh, sketchId: dialog.target.obj3d.name }) dispatch({ type: 'rx-extrusion', mesh, sketchId: dialog.target.obj3d.name })
if (sc.activeSketch == dialog.target) { if (sce.activeSketch == dialog.target) {
dispatch({ type: 'finish-sketch' }) dispatch({ type: 'finish-sketch' })
dialog.target.deactivate() dialog.target.deactivate()
} }
dispatch({ type: "clear-dialog" }) dispatch({ type: "clear-dialog" })
sc.render() sce.render()
} }
const extrudeCancel = () => { const extrudeCancel = () => {
if (sc.activeSketch == dialog.target) { // if extrude dialog launched from sketch mode we set dialog back to the sketch dialog if (sce.activeSketch == dialog.target) { // if extrude dialog launched from sketch mode we set dialog back to the sketch dialog
dispatch({ type: 'set-dialog', action: 'sketch' }) dispatch({ type: 'set-dialog', action: 'sketch' })
} else { } else {
dispatch({ type: "clear-dialog" }) dispatch({ type: "clear-dialog" })
@ -46,41 +48,41 @@ export const Dialog = () => {
const extrudeEdit = () => { const extrudeEdit = () => {
dialog.target.userData.featureInfo[1] = ref.current.value dialog.target.userData.featureInfo[1] = ref.current.value
sc.refreshNode(dialog.target.name, treeEntries) sce.refreshNode(dialog.target.name, treeEntries)
dispatch({ type: 'set-modified', status: true }) dispatch({ type: 'set-modified', status: true })
dispatch({ type: "clear-dialog" }) dispatch({ type: "clear-dialog" })
sc.render() sce.render()
} }
const extrudeEditCancel = () => dispatch({ type: "clear-dialog" }) const extrudeEditCancel = () => dispatch({ type: "clear-dialog" })
const sketchDone = () => { const sketchDone = () => {
if (sc.activeSketch.hasChanged if (sce.activeSketch.hasChanged
|| sc.activeSketch.idOnActivate != id || sce.activeSketch.idOnActivate != id
|| sc.activeSketch.c_idOnActivate != sc.activeSketch.c_id || sce.activeSketch.c_idOnActivate != sce.activeSketch.c_id
) { ) {
sc.refreshNode(sc.activeSketch.obj3d.name, treeEntries) sce.refreshNode(sce.activeSketch.obj3d.name, treeEntries)
dispatch({ type: 'set-modified', status: true }) dispatch({ type: 'set-modified', status: true })
} }
dispatch({ type: 'finish-sketch' }) dispatch({ type: 'finish-sketch' })
sc.activeSketch.deactivate() sce.activeSketch.deactivate()
sc.render() sce.render()
dispatch({ type: "clear-dialog" }) dispatch({ type: "clear-dialog" })
} }
const sketchCancel = () => { const sketchCancel = () => {
if (!sc.activeSketch.hasChanged if (!sce.activeSketch.hasChanged
&& sc.activeSketch.idOnActivate == id && sce.activeSketch.idOnActivate == id
&& sc.activeSketch.c_idOnActivate == sc.activeSketch.c_id && sce.activeSketch.c_idOnActivate == sce.activeSketch.c_id
) { ) {
if (sc.newSketch) { if (sce.newSketch) {
dispatch({ type: 'delete-node', id: sc.activeSketch.obj3d.name }) dispatch({ type: 'delete-node', id: sce.activeSketch.obj3d.name })
sc.sid -= 1 sce.sid -= 1
} else { } else {
dispatch({ type: "restore-sketch" }) dispatch({ type: "restore-sketch" })
} }
@ -88,8 +90,8 @@ export const Dialog = () => {
dispatch({ type: 'finish-sketch' }) dispatch({ type: 'finish-sketch' })
sc.activeSketch.deactivate() sce.activeSketch.deactivate()
sc.render() sce.render()
dispatch({ type: "clear-dialog" }) dispatch({ type: "clear-dialog" })
} }

View File

@ -3,6 +3,9 @@ import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
import {sce} from './app'
export const DropDown = () => { export const DropDown = () => {
const arr = [ const arr = [
@ -30,17 +33,15 @@ export const DropDown = () => {
} }
const handleInsideClick = (e) => { const handleInsideClick = async (e) => {
// handles click inside dropdown, business logic here // handles click inside dropdown, business logic here
const idx = Array.prototype.indexOf.call(e.target.parentNode.children, e.target) const idx = Array.prototype.indexOf.call(e.target.parentNode.children, e.target)
if (idx !== -1) { if (idx !== -1) {
console.log(idx) console.log(idx)
fetch(arr[idx][0]) const res = await fetch(arr[idx][0])
.then(res => res.text()) const text = await res.text()
.then(text => { dispatch({ type: 'restore-state', state: sce.loadState(text) })
dispatch({ type: 'restore-state', state: sc.loadState(text) }) sce.render()
sc.render()
})
} }
} }
const fileHandle = useSelector(state => state.ui.fileHandle) const fileHandle = useSelector(state => state.ui.fileHandle)

View File

@ -10,6 +10,8 @@ import {
fileSave, fileSave,
} from 'browser-fs-access'; } from 'browser-fs-access';
import {sce} from './app'
// https://web.dev/file-system-access/ // https://web.dev/file-system-access/
const link = document.createElement('a'); const link = document.createElement('a');
@ -24,7 +26,7 @@ function saveLegacy(blob, filename) {
var tzoffset = (new Date()).getTimezoneOffset() * 60000; var tzoffset = (new Date()).getTimezoneOffset() * 60000;
export function STLExport(filename) { export function STLExport(filename) {
const result = STLexp.parse(sc.selected[0], { binary: true }); const result = STLexp.parse(sce.selected[0], { binary: true });
const time = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -5).replace(/:/g, '-'); const time = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -5).replace(/:/g, '-');
saveLegacy(new Blob([result], { type: 'model/stl' }), `${filename}_${time}.stl`); saveLegacy(new Blob([result], { type: 'model/stl' }), `${filename}_${time}.stl`);
} }
@ -92,7 +94,7 @@ export async function openFile(dispatch) {
try { try {
const text = await file.text();; const text = await file.text();;
dispatch({ type: 'restore-state', state: sc.loadState(text) }) dispatch({ type: 'restore-state', state: sce.loadState(text) })
dispatch({ type: 'set-file-handle', fileHandle:file.handle }) dispatch({ type: 'set-file-handle', fileHandle:file.handle })
} catch (ex) { } catch (ex) {

View File

@ -12,6 +12,9 @@ import { Dialog } from './dialog'
import { DropDown } from './dropDown' import { DropDown } from './dropDown'
import { STLExport, saveFile, openFile, verifyPermission } from './fileHelpers' import { STLExport, saveFile, openFile, verifyPermission } from './fileHelpers'
import { sce } from './app'
// import { serial, deserial} from './app'
export const NavBar = () => { export const NavBar = () => {
const dispatch = useDispatch() const dispatch = useDispatch()
const sketchActive = useSelector(state => state.ui.sketchActive) const sketchActive = useSelector(state => state.ui.sketchActive)
@ -20,15 +23,15 @@ export const NavBar = () => {
const modified = useSelector(state => state.ui.modified) const modified = useSelector(state => state.ui.modified)
const boolOp = (code) => { const boolOp = (code) => {
if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) { if (sce.selected.length != 2 || !sce.selected.every(e => e.userData.type == 'mesh')) {
alert('please first select two bodies for boolean operation') alert('please first select two bodies for boolean operation')
return return
} }
const [m1, m2] = sc.selected const [m1, m2] = sce.selected
const mesh = sc.boolOp(m1, m2, code) const mesh = sce.boolOp(m1, m2, code)
sc.obj3d.add(mesh) sce.obj3d.add(mesh)
dispatch({ dispatch({
type: 'set-entry-visibility', obj: { type: 'set-entry-visibility', obj: {
@ -43,13 +46,13 @@ export const NavBar = () => {
}) })
sc.render() sce.render()
forceUpdate() forceUpdate()
} }
const addSketch = () => { const addSketch = () => {
const sketch = sc.addSketch() const sketch = sce.addSketch()
if (!sketch) { if (!sketch) {
alert('please select a plane or 3 points to set the sketch plane') alert('please select a plane or 3 points to set the sketch plane')
return return
@ -59,7 +62,7 @@ export const NavBar = () => {
sketch.activate() sketch.activate()
sc.render() sce.render()
dispatch({ type: 'set-dialog', action: 'sketch' }) dispatch({ type: 'set-dialog', action: 'sketch' })
@ -74,11 +77,11 @@ export const NavBar = () => {
useEffect(() => { useEffect(() => {
const onBeforeUnload = (e) => { const onBeforeUnload = (e) => {
if (modified || if (modified ||
(sc.activeSketch && (sce.activeSketch &&
( (
sc.activeSketch.hasChanged sce.activeSketch.hasChanged
|| sc.activeSketch.idOnActivate != id || sce.activeSketch.idOnActivate != id
|| sc.activeSketch.c_idOnActivate != sc.activeSketch.c_id || sce.activeSketch.c_idOnActivate != sce.activeSketch.c_id
) )
) )
) { ) {
@ -92,30 +95,31 @@ export const NavBar = () => {
useEffect(() => { // hacky way to handle mounting and unmounting mouse listeners for feature mode useEffect(() => { // hacky way to handle mounting and unmounting mouse listeners for feature mode
if (!sketchActive) { if (!sketchActive) {
sc.canvas.addEventListener('pointermove', sc.onHover) sce.canvas.addEventListener('pointermove', sce.onHover)
sc.canvas.addEventListener('pointerdown', sc.onPick) sce.canvas.addEventListener('pointerdown', sce.onPick)
return () => { return () => {
sc.canvas.removeEventListener('pointermove', sc.onHover) sce.canvas.removeEventListener('pointermove', sce.onHover)
sc.canvas.removeEventListener('pointerdown', sc.onPick) sce.canvas.removeEventListener('pointerdown', sce.onPick)
} }
} }
}, [sketchActive]) }, [sketchActive])
const sketchModeButtons = [ const sketchModeButtons = [
[Icon.Extrude, () => { [Icon.Extrude, () => {
dispatch({ type: 'set-dialog', action: 'extrude', target: sc.activeSketch }) dispatch({ type: 'set-dialog', action: 'extrude', target: sce.activeSketch })
}, 'Extrude'], }, 'Extrude'],
[Icon.Line, () => sc.activeSketch.command('l'), 'Line (L)'], [Icon.Line, () => sce.activeSketch.command('l'), 'Line (L)'],
[Icon.Arc, () => sc.activeSketch.command('a'), 'Arc (A)'], [Icon.Arc, () => sce.activeSketch.command('a'), 'Arc (A)'],
[Icon.Dimension, () => sc.activeSketch.command('d'), 'Dimension (D)'], [Icon.Dimension, () => sce.activeSketch.command('d'), 'Dimension (D)'],
[Icon.Coincident, () => sc.activeSketch.command('c'), 'Coincident (C)'], [Icon.Coincident, () => sce.activeSketch.command('c'), 'Coincident (C)'],
[Icon.Vertical, () => sc.activeSketch.command('v'), 'Vertical (V)'], [Icon.Vertical, () => sce.activeSketch.command('v'), 'Vertical (V)'],
[Icon.Horizontal, () => sc.activeSketch.command('h'), 'Horizontal (H)'], [Icon.Horizontal, () => sce.activeSketch.command('h'), 'Horizontal (H)'],
[Icon.Tangent, () => sc.activeSketch.command('t'), 'Tangent (T)'], [Icon.Tangent, () => sce.activeSketch.command('t'), 'Tangent (T)'],
[MdSave, [MdSave,
async () => { async () => {
saveFile(fileHandle, JSON.stringify([id, sc.sid, sc.mid, treeEntries]), dispatch) saveFile(fileHandle, JSON.stringify([id, sce.sid, sce.mid, treeEntries]), dispatch)
// saveFile(fileHandle, serial([id, sce.sid, sce.mid, treeEntries]), dispatch)
} }
, 'Save'], , 'Save'],
] ]
@ -125,7 +129,7 @@ export const NavBar = () => {
[FaEdit, addSketch, 'Sketch'], [FaEdit, addSketch, 'Sketch'],
[Icon.Extrude, () => { [Icon.Extrude, () => {
try { try {
dispatch({ type: 'set-dialog', action: 'extrude', target: treeEntries.byId[sc.selected[0].name] }) dispatch({ type: 'set-dialog', action: 'extrude', target: treeEntries.byId[sce.selected[0].name] })
} catch (err) { } catch (err) {
console.error(err) console.error(err)
alert('please select a sketch from the left pane extrude') alert('please select a sketch from the left pane extrude')
@ -138,23 +142,24 @@ export const NavBar = () => {
[Icon.Intersect, () => boolOp('i'), 'Intersect'], [Icon.Intersect, () => boolOp('i'), 'Intersect'],
[MdInsertDriveFile, () => { [MdInsertDriveFile, () => {
if (!confirmDiscard()) return if (!confirmDiscard()) return
sc.newPart() sce.newPart()
dispatch({ type: 'new-part' }) dispatch({ type: 'new-part' })
sc.render() sce.render()
}, 'New'], }, 'New'],
[MdSave, [MdSave,
() => { () => {
saveFile(fileHandle, JSON.stringify([id, sc.sid, sc.mid, treeEntries]), dispatch) saveFile(fileHandle, JSON.stringify([id, sce.sid, sce.mid, treeEntries]), dispatch)
// saveFile(fileHandle, serial([id, sce.sid, sce.mid, treeEntries]), dispatch)
} }
, 'Save'], , 'Save'],
[MdFolder, () => { [MdFolder, () => {
if (!confirmDiscard()) return if (!confirmDiscard()) return
openFile(dispatch).then( openFile(dispatch).then(
sc.render sce.render
) )
}, 'Open'], }, 'Open'],
[Icon.Stl, () => { [Icon.Stl, () => {
if (sc.selected[0] && sc.selected[0].userData.type == 'mesh') { if (sce.selected[0] && sce.selected[0].userData.type == 'mesh') {
STLExport(fileHandle ? fileHandle.name.replace(/\.[^/.]+$/, "") : 'untitled') STLExport(fileHandle ? fileHandle.name.replace(/\.[^/.]+$/, "") : 'untitled')
} else { } else {
alert('please first select one body to export') alert('please first select one body to export')

View File

@ -3,6 +3,7 @@
import { DepTree } from './depTree' import { DepTree } from './depTree'
import update from 'immutability-helper' import update from 'immutability-helper'
import { combineReducers } from 'redux'; import { combineReducers } from 'redux';
import { sce } from './app'
const defaultState = { const defaultState = {
byId: {}, byId: {},
@ -38,13 +39,13 @@ export function treeEntries(state = defaultState, action) {
}) })
case 'finish-sketch': case 'finish-sketch':
return update(state, { return update(state, {
visible: { [sc.activeSketch.obj3d.name]: { $set: false } }, visible: { [sce.activeSketch.obj3d.name]: { $set: false } },
}) })
case 'restore-sketch': case 'restore-sketch':
const sketch = sc.loadSketch(cache) const sketch = sce.loadSketch(cache)
const deletedObj = sc.obj3d.children.splice(state.order[sc.activeSketch.obj3d.name] + 1, 1, const deletedObj = sce.obj3d.children.splice(state.order[sce.activeSketch.obj3d.name] + 1, 1,
sketch.obj3d sketch.obj3d
)[0] )[0]
@ -53,10 +54,10 @@ export function treeEntries(state = defaultState, action) {
if (obj.material) obj.material.dispose() if (obj.material) obj.material.dispose()
}) })
sc.activeSketch = sketch sce.activeSketch = sketch
return update(state, { return update(state, {
byId: { [sc.activeSketch.obj3d.name]: { $set: sketch } }, byId: { [sce.activeSketch.obj3d.name]: { $set: sketch } },
}) })
case 'rx-extrusion': case 'rx-extrusion':

View File

@ -6,6 +6,8 @@ import { MdVisibilityOff, MdVisibility, MdDelete } from 'react-icons/md'
import { FaCube, FaEdit } from 'react-icons/fa' import { FaCube, FaEdit } from 'react-icons/fa'
import {sce} from './app'
export const Tree = () => { export const Tree = () => {
const treeEntries = useSelector(state => state.treeEntries) const treeEntries = useSelector(state => state.treeEntries)
const fileHandle = useSelector(state => state.ui.fileHandle) const fileHandle = useSelector(state => state.ui.fileHandle)
@ -53,19 +55,19 @@ const TreeEntry = ({ entId }) => {
return <div className='btn text-gray-200 select-none flex justify-start w-full h-7 items-center text-sm' return <div className='btn text-gray-200 select-none flex justify-start w-full h-7 items-center text-sm'
onDoubleClick={() => { onDoubleClick={() => {
if (obj3d.userData.type == 'sketch') { if (obj3d.userData.type == 'sketch') {
if (sc.activeSketch) { if (sce.activeSketch) {
dispatch({ type: 'finish-sketch' }) dispatch({ type: 'finish-sketch' })
sc.activeSketch.deactivate() sce.activeSketch.deactivate()
} }
sketch.activate() sketch.activate()
dispatch({ type: 'set-active-sketch', sketch }) dispatch({ type: 'set-active-sketch', sketch })
sc.clearSelection() sce.clearSelection()
sc.activeSketch = sketch; sce.activeSketch = sketch;
dispatch({ type: 'set-dialog', action: 'sketch' }) dispatch({ type: 'set-dialog', action: 'sketch' })
sc.render() sce.render()
} else if (obj3d.userData.featureInfo.length == 2) { } else if (obj3d.userData.featureInfo.length == 2) {
dispatch({ type: 'set-dialog', action: 'extrude-edit', target: treeEntriesById[entId] }) dispatch({ type: 'set-dialog', action: 'extrude-edit', target: treeEntriesById[entId] })
} }
@ -79,37 +81,37 @@ const TreeEntry = ({ entId }) => {
obj3d.visible = true obj3d.visible = true
} }
sc.setHover(obj3d, 1) sce.setHover(obj3d, 1)
sc.render() sce.render()
}} }}
onPointerLeave={() => { onPointerLeave={() => {
if (!mouseOn) return if (!mouseOn) return
setMouseOn(false) setMouseOn(false)
if (obj3d.userData.type == 'sketch' if (obj3d.userData.type == 'sketch'
&& !sc.selected.includes(obj3d) && !sce.selected.includes(obj3d)
&& !visible && !visible
) { ) {
obj3d.visible = false obj3d.visible = false
} }
if (sc.selected.includes(obj3d)) return if (sce.selected.includes(obj3d)) return
sc.setHover(obj3d, 0) sce.setHover(obj3d, 0)
sc.render() sce.render()
}} }}
onClick={() => { onClick={() => {
const idx = sc.selected.indexOf(obj3d) const idx = sce.selected.indexOf(obj3d)
if (idx == -1) { if (idx == -1) {
sc.selected.push(obj3d) sce.selected.push(obj3d)
sc.setHover(obj3d, 1) sce.setHover(obj3d, 1)
} else { } else {
sc.setHover(sc.selected[idx], 0) sce.setHover(sce.selected[idx], 0)
sc.selected.splice(idx, 1) sce.selected.splice(idx, 1)
} }
sc.render() sce.render()
}} }}
tooltip= {obj3d.name[0] !='(' && "double click to edit"} tooltip= {obj3d.name[0] !='(' && "double click to edit"}
@ -125,7 +127,7 @@ const TreeEntry = ({ entId }) => {
<MdDelete className='btn-green h-full w-auto p-1.5' <MdDelete className='btn-green h-full w-auto p-1.5'
onClick={(e) => { onClick={(e) => {
dispatch({ type: 'delete-node', id: entId }) dispatch({ type: 'delete-node', id: entId })
sc.render() sce.render()
e.stopPropagation() e.stopPropagation()
}} }}
/> />
@ -142,7 +144,7 @@ const TreeEntry = ({ entId }) => {
obj3d.traverse((e) => e.layers.disable(1)) obj3d.traverse((e) => e.layers.disable(1))
} }
sc.render() sce.render()
forceUpdate() forceUpdate()
}} }}
/> />
@ -158,7 +160,7 @@ const TreeEntry = ({ entId }) => {
e.layers.enable(1) e.layers.enable(1)
}) })
} }
sc.render() sce.render()
forceUpdate() forceUpdate()
}} }}
/> />

View File

@ -23,7 +23,7 @@
<div id="labels"></div> <div id="labels"></div>
<div id="stats"></div> <div id="stats"></div>
<script src="app.bundle.js"></script> <script src="app.bundle.js"></script>
<script src="scene.bundle.js"></script> <!-- <script src="scene.bundle.js"></script> -->
<script src="solver.js"></script> <script src="solver.js"></script>
</body> </body>

View File

@ -5,7 +5,7 @@ const tailwindcss = require('tailwindcss')
module.exports = { module.exports = {
entry: { entry: {
app: './src/react/app.jsx', app: './src/react/app.jsx',
scene: './src/Scene.js', // scene: './src/Scene.js',
}, },
output: { output: {
filename: '[name].bundle.js', filename: '[name].bundle.js',