working manual refresh
parent
930df2e288
commit
69b2fff6d1
57
src/Scene.js
57
src/Scene.js
|
@ -194,10 +194,10 @@ export class Scene {
|
|||
} else if (k[0] == 'e') {
|
||||
|
||||
entries[k] = loader.parse(state.byId[k])
|
||||
|
||||
|
||||
if (entries[k].userData.inverted) {
|
||||
flipBufferGeometryNormals(entries[k].geometry)
|
||||
}
|
||||
}
|
||||
|
||||
this.obj3d.add(entries[k])
|
||||
|
||||
|
@ -235,7 +235,7 @@ export class Scene {
|
|||
}
|
||||
|
||||
|
||||
boolOp(m1, m2, op) {
|
||||
boolOp(m1, m2, op, refresh = false) {
|
||||
let bspA = CSG.fromMesh(m1)
|
||||
let bspB = CSG.fromMesh(m2)
|
||||
m1.visible = false
|
||||
|
@ -275,18 +275,51 @@ export class Scene {
|
|||
|
||||
mesh.add(vertices)
|
||||
|
||||
sc.obj3d.add(mesh)
|
||||
if (!refresh) {
|
||||
sc.obj3d.add(mesh)
|
||||
|
||||
this.store.dispatch({
|
||||
type: 'set-entry-visibility', obj: {
|
||||
[m1.name]: false,
|
||||
[m2.name]: false,
|
||||
[mesh.name]: true,
|
||||
}
|
||||
})
|
||||
this.store.dispatch({
|
||||
type: 'set-entry-visibility', obj: {
|
||||
[m1.name]: false,
|
||||
[m2.name]: false,
|
||||
[mesh.name]: true,
|
||||
}
|
||||
})
|
||||
|
||||
this.store.dispatch({
|
||||
type: 'rx-boolean', mesh, deps: [m1.name, m2.name]
|
||||
})
|
||||
} else {
|
||||
return mesh
|
||||
}
|
||||
|
||||
return mesh
|
||||
}
|
||||
|
||||
refreshNode(id) {
|
||||
let curId
|
||||
let que = [id]
|
||||
let idx = 0
|
||||
|
||||
const { byId, tree } = this.store.getState().treeEntries
|
||||
while (idx < que.length) {
|
||||
curId = que[idx++]
|
||||
|
||||
const info = byId[curId].userData.featureInfo
|
||||
let newNode
|
||||
if (info.length == 2) {
|
||||
newNode = this.extrude(byId[info[0]], info[1], true)
|
||||
} else if (info.length == 3) {
|
||||
newNode = this.boolOp(byId[info[0]], byId[info[1]], info[2], true)
|
||||
}
|
||||
|
||||
byId[curId].geometry.copy(newNode.geometry)
|
||||
|
||||
for (let k in tree[curId]) {
|
||||
que.push(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -310,12 +310,36 @@ class Sketch {
|
|||
|
||||
for (let j = 0; j < link.length; j++) {
|
||||
const obj = this.obj3d.children[i + j]
|
||||
obj.geometry.dispose()
|
||||
obj.material.dispose()
|
||||
// obj.geometry.dispose()
|
||||
// obj.material.dispose()
|
||||
|
||||
for (let c_id of obj.userData.constraints.slice()) { // i hate js
|
||||
obj.traverse((ob) => {
|
||||
if (ob.geometry) ob.geometry.dispose()
|
||||
if (ob.material) ob.material.dispose()
|
||||
})
|
||||
|
||||
// collect all coincident constraints to be reconnected
|
||||
// after deleting this point
|
||||
let arr = []
|
||||
let cons
|
||||
for (let c_id of obj.userData.constraints.slice()) {
|
||||
// i hate js, slice is important because deleteContraints mutates constraints array
|
||||
cons = this.constraints.get(c_id)
|
||||
if (cons[0] == 'points_coincident') {
|
||||
arr.push(cons[2][0] == obj.name ?
|
||||
cons[2][1] : cons[2][0]
|
||||
)
|
||||
}
|
||||
this.deleteConstraints(c_id)
|
||||
}
|
||||
|
||||
for (let i = 0; i < arr.length - 1; i++) {
|
||||
setCoincident.call(this,[
|
||||
this.obj3d.children[this.objIdx.get(arr[i])],
|
||||
this.obj3d.children[this.objIdx.get(arr[i+1])]
|
||||
])
|
||||
}
|
||||
|
||||
obj.userData.constraints = []
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
import { color } from './shared'
|
||||
|
||||
export async function setCoincident() {
|
||||
let selection = await this.awaitSelection({ point: 2 }, { point: 1, line: 1 })
|
||||
if (selection == null) return;
|
||||
export async function setCoincident(sel) {
|
||||
let selection
|
||||
if (sel === undefined) {
|
||||
selection = await this.awaitSelection({ point: 2 }, { point: 1, line: 1 })
|
||||
if (selection == null) return;
|
||||
} else {
|
||||
selection = sel
|
||||
}
|
||||
|
||||
|
||||
if (selection.every(e => e.userData.type == 'point')) {
|
||||
this.constraints.set(++this.c_id,
|
||||
[
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as THREE from '../node_modules/three/src/Three';
|
||||
import { color } from './shared'
|
||||
export function extrude(sketch, depth) {
|
||||
export function extrude(sketch, depth, refresh=false) {
|
||||
|
||||
let constraints = sketch.constraints;
|
||||
let linkedObjs = sketch.linkedObjs;
|
||||
|
@ -10,7 +10,7 @@ export function extrude(sketch, depth) {
|
|||
let v2s = []
|
||||
|
||||
function findPair(node) {
|
||||
console.log(node.name,'xx')
|
||||
// console.log(node.name, 'xx')
|
||||
if (node.userData.construction) return;
|
||||
visited.add(node)
|
||||
let linkedObj = linkedObjs.get(node.userData.l_id)
|
||||
|
@ -43,7 +43,7 @@ export function extrude(sketch, depth) {
|
|||
)
|
||||
]
|
||||
if (d == children[2]) {
|
||||
console.log('pair found')
|
||||
// console.log('pair found')
|
||||
};
|
||||
findTouching(d)
|
||||
|
||||
|
@ -51,19 +51,19 @@ export function extrude(sketch, depth) {
|
|||
|
||||
|
||||
function findTouching(node) {
|
||||
console.log(node.name,'yy')
|
||||
// console.log(node.name, 'yy')
|
||||
for (let t of node.userData.constraints) {
|
||||
console.log(constraints.get(t)[2],node.name )
|
||||
// console.log(constraints.get(t)[2], node.name)
|
||||
if (constraints.get(t)[0] != 'points_coincident') continue
|
||||
for (let c of constraints.get(t)[2]) {
|
||||
if (c == -1) continue;
|
||||
const d = children[objIdx.get(c)]
|
||||
if (d == node) continue;
|
||||
if (d == children[2]) {
|
||||
console.log('loop found')
|
||||
// console.log('loop found')
|
||||
} else {
|
||||
// if (!visited.has(d)) {
|
||||
findPair(d)
|
||||
findPair(d)
|
||||
// }
|
||||
};
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ export function extrude(sketch, depth) {
|
|||
}
|
||||
|
||||
|
||||
findPair(children[2]) //??? need fixing
|
||||
findPair(children[sketch.geomStartIdx + 1]) // ?? possibly allow user select search start point
|
||||
|
||||
const shape = new THREE.Shape(v2s);
|
||||
// const extrudeSettings = { depth: Math.abs(depth), bevelEnabled: false };
|
||||
|
@ -88,27 +88,9 @@ export function extrude(sketch, depth) {
|
|||
|
||||
const mesh = new THREE.Mesh(geometry, material)
|
||||
|
||||
// const material = new THREE.MeshPhongMaterial({
|
||||
// color: color.mesh,
|
||||
// });
|
||||
|
||||
// const wireframe = new THREE.WireframeGeometry( geometry );
|
||||
// const mesh = new THREE.LineSegments( wireframe );
|
||||
// mesh.material.depthTest = true;
|
||||
// mesh.material.opacity = 0.8;
|
||||
// mesh.material.transparent = true;
|
||||
|
||||
// const edges = new THREE.EdgesGeometry( geometry, 15 );
|
||||
// edges.type = 'BufferGeometry'
|
||||
// edges.parameters = undefined
|
||||
|
||||
// const mesh = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( { color: 0x000000 } ) );
|
||||
|
||||
|
||||
|
||||
mesh.name = 'e' + this.mid++
|
||||
// mesh.name = 'm' + sketch.obj3d.name.slice(1)
|
||||
// mesh.name = 'e' + sketch.obj3d.name.slice(1)
|
||||
mesh.userData.type = 'mesh'
|
||||
mesh.userData.featureInfo = [sketch.obj3d.name, depth]
|
||||
mesh.layers.enable(1)
|
||||
|
@ -119,12 +101,6 @@ export function extrude(sketch, depth) {
|
|||
|
||||
mesh.add(vertices)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
mesh.matrixAutoUpdate = false;
|
||||
mesh.matrix.multiply(sketch.obj3d.matrix)
|
||||
|
||||
|
@ -134,25 +110,22 @@ export function extrude(sketch, depth) {
|
|||
}
|
||||
|
||||
|
||||
this.obj3d.add(mesh)
|
||||
if (!refresh) {
|
||||
this.obj3d.add(mesh)
|
||||
|
||||
this.store.dispatch({ type: 'rx-extrusion', mesh, sketchId: sketch.obj3d.name })
|
||||
this.store.dispatch({ type: 'rx-extrusion', mesh, sketchId: sketch.obj3d.name })
|
||||
|
||||
// sketch.userData
|
||||
if (this.activeSketch == sketch) {
|
||||
this.activeSketch = null
|
||||
sketch.deactivate()
|
||||
if (this.activeSketch == sketch) {
|
||||
sketch.deactivate()
|
||||
}
|
||||
this.render()
|
||||
} else {
|
||||
return mesh
|
||||
}
|
||||
|
||||
// this.clearSelection()
|
||||
this.render()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export function flipBufferGeometryNormals(geometry) {
|
||||
//https://stackoverflow.com/a/54496265
|
||||
const tempXYZ = [0, 0, 0];
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
|
||||
export class DepTree {
|
||||
constructor(obj) {
|
||||
if (obj) {
|
||||
this.order = { ...obj.order }
|
||||
this.byId = { ...obj.byId }
|
||||
this.allIds = [...obj.allIds]
|
||||
this.order = { ...obj.order }
|
||||
this.byId = { ...obj.byId }
|
||||
this.allIds = [...obj.allIds]
|
||||
|
||||
this.tree = {}
|
||||
for (let k in obj.tree) {
|
||||
this.tree[k] = { ...obj.tree[k] }
|
||||
}
|
||||
|
||||
} else {
|
||||
this.tree = {}
|
||||
this.order = {}
|
||||
this.allIds = []
|
||||
this.tree = {}
|
||||
for (let k in obj.tree) {
|
||||
this.tree[k] = { ...obj.tree[k] }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
addParent(id) {
|
||||
|
@ -71,7 +66,7 @@ export class DepTree {
|
|||
|
||||
const deletedObj = sc.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.material) obj.material.dispose()
|
||||
})
|
||||
|
@ -95,6 +90,9 @@ export class DepTree {
|
|||
}
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -103,7 +101,7 @@ export class DepTree {
|
|||
// const dt = new DepTree()
|
||||
// dt.addParent('r1')
|
||||
// dt.addParent('r2')
|
||||
// dt.addChild('r3', 'r1', 'r2')
|
||||
// dt.addChild('r3', 'r1', 'r2')s
|
||||
// dt.addParent('r4')
|
||||
// dt.addChild('r5', 'r4', 'r3')
|
||||
// dt.addChild('r6', 'r1', 'r5')
|
||||
|
@ -128,3 +126,6 @@ export class DepTree {
|
|||
// allIds: [ 'r1', 'r2', 'r3', 'r4', 'r8' ]
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -22,21 +22,28 @@ export const Dialog = ({ dialog, setDialog }) => {
|
|||
}, [])
|
||||
|
||||
const extrude = () => {
|
||||
let sketch
|
||||
if (sc.activeSketch) {
|
||||
sc.extrude(sc.activeSketch, ref.current.value)
|
||||
setDialog(null)
|
||||
sketch = sc.activeSketch
|
||||
} else if (sc.selected.length === 1 && sc.selected[0].userData.type == 'sketch') {
|
||||
sc.extrude(treeEntriesById[sc.selected[0].name], ref.current.value)
|
||||
setDialog(null)
|
||||
sketch = treeEntriesById[sc.selected[0].name]
|
||||
} else {
|
||||
console.log('invalid selection')
|
||||
return
|
||||
}
|
||||
|
||||
setDialog(null)
|
||||
sc.extrude(sketch, ref.current.value)
|
||||
|
||||
sc.render()
|
||||
forceUpdate()
|
||||
}
|
||||
|
||||
|
||||
const [_, forceUpdate] = useReducer(x => x + 1, 0);
|
||||
|
||||
return <div className='dialog w-40 h-10 flex items-center bg-gray-700'>
|
||||
{/* return <div className='w-40 h-full flex items-center bg-gray-700'> */}
|
||||
<input className='w-1/2' type="number" {...useNumField(1)} step="0.1" ref={ref} />
|
||||
<Icon.Flip className="btn w-auto h-full p-2"
|
||||
onClick={() => ref.current.value *= -1}
|
||||
|
|
|
@ -17,8 +17,7 @@ export const NavBar = ({ setDialog }) => {
|
|||
const boolOp = (code) => {
|
||||
if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) return
|
||||
const [m1, m2] = sc.selected
|
||||
const mesh = sc.boolOp(m1, m2, code)
|
||||
dispatch({ type: 'rx-boolean', mesh, deps: [m1.name, m2.name] })
|
||||
sc.boolOp(m1, m2, code)
|
||||
sc.render()
|
||||
forceUpdate()
|
||||
}
|
||||
|
@ -65,8 +64,7 @@ export const NavBar = ({ setDialog }) => {
|
|||
|
||||
|
||||
const btnz2 = [
|
||||
[FaEdit, addSketch, 'Sketch [s]']
|
||||
,
|
||||
[FaEdit, addSketch, 'Sketch [s]'],
|
||||
[Icon.Extrude, extrude, 'Extrude [e]'],
|
||||
[Icon.Union, () => boolOp('u'), 'Union'],
|
||||
[Icon.Subtract, () => boolOp('s'), 'Subtract'],
|
||||
|
|
|
@ -48,7 +48,7 @@ export function treeEntries(state = defaultState, action) {
|
|||
},
|
||||
allIds: { $push: [action.mesh.name] },
|
||||
tree: {
|
||||
[action.sketchId]: { [action.mesh.name]: { $set: true} },
|
||||
[action.sketchId]: { [action.mesh.name]: { $set: true } },
|
||||
[action.mesh.name]: { $set: {} }
|
||||
},
|
||||
order: { [action.mesh.name]: { $set: state.allIds.length } },
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
import React, { useReducer, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { MdVisibilityOff, MdVisibility, MdDelete } from 'react-icons/md'
|
||||
import { MdVisibilityOff, MdVisibility, MdDelete, MdRefresh } from 'react-icons/md'
|
||||
|
||||
import { FaCube, FaEdit } from 'react-icons/fa'
|
||||
|
||||
import { DepTree } from './depTree.mjs'
|
||||
|
||||
export const Tree = () => {
|
||||
const treeEntries = useSelector(state => state.treeEntries)
|
||||
|
||||
|
@ -26,6 +28,7 @@ const treeIcons = {
|
|||
|
||||
const TreeEntry = ({ entId }) => {
|
||||
|
||||
const state = useSelector(state => state.treeEntries)
|
||||
const treeEntries = useSelector(state => state.treeEntries.byId)
|
||||
const dispatch = useDispatch()
|
||||
|
||||
|
@ -110,6 +113,14 @@ const TreeEntry = ({ entId }) => {
|
|||
e.stopPropagation()
|
||||
}}
|
||||
/>
|
||||
<MdRefresh className='btn-green h-full w-auto p-1.5'
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
|
||||
sc.refreshNode(entId)
|
||||
sc.render()
|
||||
}}
|
||||
/>
|
||||
|
||||
{
|
||||
visible ?
|
||||
|
|
|
@ -166,7 +166,7 @@ function setHover(obj, state, meshHover = true) {
|
|||
break;
|
||||
case 'mesh':
|
||||
if (meshHover) {
|
||||
// obj.material.emissive.set(colObj.emissive)
|
||||
obj.material.emissive.set(colObj.emissive)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
|
5
todo.txt
5
todo.txt
|
@ -30,16 +30,15 @@ tangent // done to the best of my ability
|
|||
|
||||
extrude dialogue / done
|
||||
better default ent names / done
|
||||
loopfind especially arc, // fixed for single looop, good enough, maybe stretch goal of selecting search start pt
|
||||
dim tag delete //resolved
|
||||
|
||||
|
||||
|
||||
-unable to delete arc
|
||||
hover not clearing sometimes in sketch
|
||||
dim tags are not clearing
|
||||
|
||||
|
||||
auto update extrude
|
||||
loopfind especially arc
|
||||
file save, stl export
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue