working dependency tree

master
howard 2021-04-05 21:52:19 -07:00
parent 40a692ed6a
commit 3b49000e2b
11 changed files with 424 additions and 132 deletions

13
package-lock.json generated
View File

@ -10,6 +10,7 @@
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"css-loader": "^5.1.3", "css-loader": "^5.1.3",
"gh-pages": "^3.1.0", "gh-pages": "^3.1.0",
"immutability-helper": "^3.1.1",
"mini-css-extract-plugin": "^1.4.0", "mini-css-extract-plugin": "^1.4.0",
"postcss": "^8.2.9", "postcss": "^8.2.9",
"postcss-loader": "^5.2.0", "postcss-loader": "^5.2.0",
@ -3633,6 +3634,12 @@
"postcss": "^8.1.0" "postcss": "^8.1.0"
} }
}, },
"node_modules/immutability-helper": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-3.1.1.tgz",
"integrity": "sha512-Q0QaXjPjwIju/28TsugCHNEASwoCcJSyJV3uO1sOIQGI0jKgm9f41Lvz0DZj3n46cNCyAZTsEYoY4C2bVRUzyQ==",
"dev": true
},
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -11406,6 +11413,12 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"immutability-helper": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-3.1.1.tgz",
"integrity": "sha512-Q0QaXjPjwIju/28TsugCHNEASwoCcJSyJV3uO1sOIQGI0jKgm9f41Lvz0DZj3n46cNCyAZTsEYoY4C2bVRUzyQ==",
"dev": true
},
"import-fresh": { "import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",

View File

@ -11,6 +11,7 @@
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"css-loader": "^5.1.3", "css-loader": "^5.1.3",
"gh-pages": "^3.1.0", "gh-pages": "^3.1.0",
"immutability-helper": "^3.1.1",
"mini-css-extract-plugin": "^1.4.0", "mini-css-extract-plugin": "^1.4.0",
"postcss": "^8.2.9", "postcss": "^8.2.9",
"postcss-loader": "^5.2.0", "postcss-loader": "^5.2.0",

View File

@ -5,8 +5,7 @@ import './app.css'
import { Provider, useDispatch, useSelector } from 'react-redux' import { Provider, useDispatch, useSelector } from 'react-redux'
import { FaCube, FaEdit } from 'react-icons/fa' import { FaCube, FaEdit } from 'react-icons/fa'
import { MdEdit, MdDone, MdVisibilityOff, MdVisibility } from 'react-icons/md' import { MdEdit, MdDone, MdVisibilityOff, MdVisibility, MdDelete } from 'react-icons/md'
import { RiShape2Fill } from 'react-icons/ri'
import * as Icon from "./icons"; import * as Icon from "./icons";
import { color } from './utils/shared' import { color } from './utils/shared'
@ -22,16 +21,11 @@ export const Root = ({ store }) => (
const App = () => { const App = () => {
const dispatch = useDispatch() const dispatch = useDispatch()
const treeEntries = useSelector(state => state.treeEntries) const treeEntries = useSelector(state => state.treeEntries)
const activeSketchNid = useSelector(state => state.activeSketchNid) const activeSketchId = useSelector(state => state.activeSketchId)
// const [state, setState] = useState('x')
// useEffect(()=>{
// console.log('hereeee')
// },[state])
useEffect(() => { useEffect(() => {
if (!activeSketchNid) { if (!activeSketchId) {
sc.canvas.addEventListener('pointermove', sc.onHover) sc.canvas.addEventListener('pointermove', sc.onHover)
sc.canvas.addEventListener('pointerdown', sc.onPick) sc.canvas.addEventListener('pointerdown', sc.onPick)
return () => { return () => {
@ -39,27 +33,38 @@ const App = () => {
sc.canvas.removeEventListener('pointerdown', sc.onPick) sc.canvas.removeEventListener('pointerdown', sc.onPick)
} }
} }
}, [activeSketchNid]) }, [activeSketchId])
const btnz = [ const btnz = [
activeSketchNid ? activeSketchId ?
[MdDone, () => { [MdDone, () => {
treeEntries.byNid[activeSketchNid].deactivate() treeEntries.byId[activeSketchId].deactivate()
sc.activeSketch = null sc.activeSketch = null
// sc.activeDim = this.activeSketch.obj3d.children[1].children // sc.activeDim = this.activeSketch.obj3d.children[1].children
}, 'Finish'] : }, 'Finish'] :
[FaEdit, sc.addSketch, 'Sketch'] [FaEdit, sc.addSketch, 'Sketch']
, ,
[FaCube, () => sc.extrude(treeEntries.byNid[activeSketchNid]), 'Extrude'], [FaCube, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Extrude'],
[Icon.Union, () => sc.extrude(treeEntries.byNid[activeSketchNid]), 'Union'], [Icon.Union, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Union'],
[Icon.Subtract, subtract, 'Subtract'], [Icon.Subtract, ()=> {
[Icon.Intersect, () => sc.extrude(treeEntries.byNid[activeSketchNid]), 'Intersect'], if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) return
[Icon.Dimension, () => sc.extrude(treeEntries.byNid[activeSketchNid]), 'Dimension'], // console.log('here')
[Icon.Line, () => sc.extrude(treeEntries.byNid[activeSketchNid]), 'Line'], const [m1, m2] = sc.selected
[Icon.Arc, () => sc.extrude(treeEntries.byNid[activeSketchNid]), 'Arc'], const mesh = subtract(m1,m2)
dispatch({ type: 'rx-extrusion', mesh, deps:[m1.name,m2.name] })
sc.render()
forceUpdate()
}, 'Subtract'],
[Icon.Intersect, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Intersect'],
[Icon.Dimension, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Dimension'],
[Icon.Line, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Line'],
[Icon.Arc, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Arc'],
] ]
const [_, forceUpdate] = useReducer(x => x + 1, 0);
return <div className='absolute left-0 w-40 flex flex-col'> return <div className='absolute left-0 w-40 flex flex-col'>
{ {
btnz.map(([Icon, fcn, txt], idx) => ( btnz.map(([Icon, fcn, txt], idx) => (
@ -73,7 +78,7 @@ const App = () => {
} }
<div className=''> <div className=''>
{treeEntries.allNids.map((entId, idx) => ( {treeEntries.allIds.map((entId, idx) => (
<TreeEntry key={idx} entId={entId} /> <TreeEntry key={idx} entId={entId} />
))} ))}
</div> </div>
@ -84,9 +89,10 @@ const App = () => {
const TreeEntry = ({ entId }) => { const TreeEntry = ({ entId }) => {
const treeEntries = useSelector(state => state.treeEntries.byNid) const treeEntries = useSelector(state => state.treeEntries.byId)
const dispatch = useDispatch()
const activeSketchNid = useSelector(state => state.activeSketchNid) const activeSketchId = useSelector(state => state.activeSketchId)
let obj3d, entry; let obj3d, entry;
@ -105,7 +111,7 @@ const TreeEntry = ({ entId }) => {
return <div className='bg-gray-50 flex justify-between w-full'> return <div className='bg-gray-50 flex justify-between w-full'>
<div className='btn' <div className='btn'
onClick={() => { onClick={() => {
activeSketchNid && treeEntries[activeSketchNid].deactivate() activeSketchId && treeEntries[activeSketchId].deactivate()
entry.activate() entry.activate()
sc.activeSketch = entry; sc.activeSketch = entry;
}} }}
@ -113,6 +119,13 @@ const TreeEntry = ({ entId }) => {
<MdEdit /> <MdEdit />
</div> </div>
<div className='btn'
onClick={() => {
dispatch({type:'delete-node',id:entId})
}}
>
<MdDelete/>
</div>
{ {
vis ? vis ?
<div className='btn' <div className='btn'
@ -165,12 +178,10 @@ const TreeEntry = ({ entId }) => {
} }
const subtract = () => { const subtract = (m1,m2) => {
// //Create a bsp tree from each of the meshes // //Create a bsp tree from each of the meshes
// console.log(sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh'), "wtf") // console.log(sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh'), "wtf")
if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) return
// console.log('here')
const [m1, m2] = sc.selected
let bspA = BoolOp.fromMesh(m1) let bspA = BoolOp.fromMesh(m1)
let bspB = BoolOp.fromMesh(m2) let bspB = BoolOp.fromMesh(m2)
@ -184,9 +195,12 @@ const subtract = () => {
// //Get the resulting mesh from the result bsp, and assign meshA.material to the resulting mesh // //Get the resulting mesh from the result bsp, and assign meshA.material to the resulting mesh
let meshResult = BoolOp.toMesh(bspResult, m1.matrix, m1.material) let meshResult = BoolOp.toMesh(bspResult, m1.matrix, m1.material)
meshResult.userData.type = 'mesh'
meshResult.userData.name = `${m1.name}-${m2.name}`
sc.obj3d.add(meshResult) sc.obj3d.add(meshResult)
sc.render()
return meshResult
} }

102
src/depTree copy.js Normal file
View File

@ -0,0 +1,102 @@
class DepTree {
constructor() {
this.tree = {}
this.order = {}
this.arr = []
}
addParent(id) {
if (this.tree[id]) return
this.tree[id] = new Set()
this.order[id] = this.arr.length
this.arr.push(id)
}
addChild(childId, ...parentIds) {
for (let parentId of parentIds) {
this.tree[parentId].add(childId)
}
this.addParent(childId)
}
deleteNode(id) {
this.visited = new Set()
this.nodesToDel = []
this.dfs(id)
const idx = []
this.nodesToDel.sort((a, b) => this.order[b] - this.order[a])
for (let id of this.nodesToDel) {
idx.push(this.order[id])
this.arr.splice(this.order[id], 1)
delete this.tree[id]
delete this.order[id]
}
for (let i = idx[idx.length - 1]; i < this.arr.length; i++) {
this.order[this.arr[i]] = i
}
const nodeToDelSet = new Set(this.nodesToDel)
for (let k in this.tree) {
for (let ent of this.tree[k]) {
if (nodeToDelSet.has(ent)) {
this.tree[k].delete(ent)
}
}
}
return idx
}
dfs(id) {
this.visited.add(id)
this.nodesToDel.push(id)
for (let x of this.tree[id]) {
if (!this.visited.has(x)) {
this.dfs(x)
}
}
}
}
const dt = new DepTree()
dt.addParent('r1')
dt.addParent('r2')
dt.addChild('r3', 'r1', 'r2')
dt.addParent('r4')
dt.addChild('r5', 'r4', 'r3')
dt.addChild('r6', 'r1', 'r5')
dt.addChild('r7', 'r3', 'r5')
// const x = dt.deleteNode('r3')
// console.log(x)
// console.log(dt.arr, dt.order)
// expectd output
// [ 6, 5, 4, 2 ]
// [ 'r1', 'r2', 'r4' ] { r1: 0, r2: 1, r4: 2 }
const x = dt.deleteNode('r5')
console.log(x)
console.log(dt.tree)

120
src/depTree.mjs Normal file
View File

@ -0,0 +1,120 @@
export class DepTree {
constructor(obj) {
if (obj) {
console.log('load', obj)
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 = []
}
}
addParent(id) {
if (this.tree[id]) return
this.tree[id] = {}
this.order[id] = this.allIds.length
this.allIds.push(id)
}
addChild(childId, ...parentIds) {
for (let parentId of parentIds) {
this.tree[parentId][childId] = true;
}
this.addParent(childId)
}
deleteNode(id) {
const dfs = (id) => {
visited.add(id)
nodesToDel.push(id)
for (let k in this.tree[id]) {
if (!visited.has(k)) {
dfs(k)
}
}
}
const visited = new Set()
const nodesToDel = []
dfs(id)
nodesToDel.sort((a, b) => this.order[b] - this.order[a])
let spliceIdx;
for (let id of nodesToDel) {
spliceIdx = this.order[id]
this.allIds.splice(spliceIdx, 1)
const deletedObj = sc.obj3d.children.splice(spliceIdx + 4, 1)[0]
deletedObj.traverse((obj)=>{
if (obj.geometry) obj.geometry.dispose()
if (obj.material) obj.material.dispose()
})
delete this.tree[id]
delete this.byId[id]
delete this.order[id]
}
for (let i = spliceIdx; i < this.allIds.length; i++) {
this.order[this.allIds[i]] = i
}
const nodeToDelSet = new Set(nodesToDel)
for (let k in this.tree) {
for (let m in this.tree[k]) {
if (nodeToDelSet.has(m)) {
delete this.tree[k][m]
}
}
}
return this
}
}
// const dt = new DepTree()
// dt.addParent('r1')
// dt.addParent('r2')
// dt.addChild('r3', 'r1', 'r2')
// dt.addParent('r4')
// dt.addChild('r5', 'r4', 'r3')
// dt.addChild('r6', 'r1', 'r5')
// dt.addChild('r7', 'r3', 'r5')
// dt.addParent('r8')
// // console.log(dt)
// // const x = dt.deleteNode('r3')
// // console.log(x)
// // console.log(dt.allIds, dt.order)
// // [ 6, 5, 4, 2 ]
// // [ 'r1', 'r2', 'r4' ] { r1: 0, r2: 1, r4: 2 }
// const x = dt.deleteNode('r5')
// console.log(dt)
// DepTree {
// tree: { r1: { r3: true }, r2: { r3: true }, r3: {}, r4: {}, r8: {} },
// order: { r1: 0, r2: 1, r3: 2, r4: 3, r8: 4 },
// allIds: [ 'r1', 'r2', 'r3', 'r4', 'r8' ]
// }

View File

@ -98,7 +98,7 @@ export function extrude(sketch) {
this.render() this.render()
// sketch.visible = false // sketch.visible = false
this.store.dispatch({ type: 'rx-extrusion', mesh, sketch }) this.store.dispatch({ type: 'rx-extrusion', mesh, sketchId: sketch.obj3d.name })
} }

View File

@ -2,43 +2,64 @@
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import React from 'react' import React from 'react'
import { Root } from './app.jsx' import { Root } from './app.jsx'
import update from 'immutability-helper';
import { createStore, applyMiddleware } from 'redux' import { createStore, applyMiddleware } from 'redux'
import logger from 'redux-logger' import logger from 'redux-logger'
let _entId = 0 import { DepTree } from './depTree.mjs'
function reducer(state = {}, action) { function reducer(state = {}, action) {
switch (action.type) { switch (action.type) {
case 'rx-sketch': case 'rx-sketch':
return { return update(state, {
...state,
treeEntries: { treeEntries: {
byNid: { ...state.treeEntries.byNid, [action.obj.obj3d.name]: action.obj }, byId: { [action.obj.obj3d.name]: { $set: action.obj } },
allNids: [...state.treeEntries.allNids, action.obj.obj3d.name] allIds: { $push: [action.obj.obj3d.name] },
} tree: { [action.obj.obj3d.name]: { $set: {} } },
} order: { [action.obj.obj3d.name]: { $set: state.treeEntries.allIds.length } }
},
})
case 'set-active-sketch': case 'set-active-sketch':
return { return update(state, {
...state, activeSketchNid: action.sketch activeSketchId: { $set: action.sketch },
} })
case 'exit-sketch': case 'exit-sketch':
return { return {
...state, activeSketchNid: '' ...state, activeSketchId: ''
} }
case 'rx-extrusion': case 'rx-extrusion':
return {
...state, return update(state, {
treeEntries: { treeEntries: {
byNid: { ...state.treeEntries.byNid, [action.mesh.name]: action.mesh }, byId: {
allNids: [...state.treeEntries.allNids, action.mesh.name] [action.mesh.name]: { $set: action.mesh }
}, },
mesh2sketch: { allIds: { $push: [action.mesh.name] },
...state.mesh2sketch, tree: {
[action.sketch.obj3d.name]: action.mesh.name [action.sketchId]: { [action.mesh.name]: { $set: true } },
},
order: { [action.mesh.name]: { $set: state.treeEntries.allIds.length } }
} }
} })
case 'delete-node':
const depTree = new DepTree(state.treeEntries)
const obj = depTree.deleteNode(action.id)
return update(state, {
treeEntries: {$set: obj}
})
case 'restore-state': case 'restore-state':
return action.state return action.state
default: default:
@ -48,12 +69,13 @@ function reducer(state = {}, action) {
const preloadedState = { const preloadedState = {
treeEntries: { treeEntries: {
byNid: {}, byId: {},
allNids: [] allIds: [],
} tree: {},
order: {},
},
} }

View File

@ -9,7 +9,7 @@ import { get3PtArc } from './drawArc'
import { _vec2, _vec3, raycaster, awaitPts } from '../utils/shared' import { _vec2, _vec3, raycaster, awaitPts } from '../utils/shared'
import { replacer, reviver } from '../utils/mapJSONReplacer' import { replacer, reviver } from '../utils/mapJSONReplacer'
import { AxesHelper } from '../utils/axes' import { AxesHelper } from '../utils/axes'
import { drawDimension, _onMoveDimension, setDimLines } from './drawDimension'; import { drawDimension, _onMoveDimension, setDimLines, updateDim } from './drawDimension';
@ -114,6 +114,7 @@ class Sketch {
this.drawDimension = drawDimension.bind(this) this.drawDimension = drawDimension.bind(this)
this._onMoveDimension = _onMoveDimension.bind(this) this._onMoveDimension = _onMoveDimension.bind(this)
this.setDimLines = setDimLines.bind(this) this.setDimLines = setDimLines.bind(this)
this.updateDim = updateDim.bind(this)
this.awaitPts = awaitPts.bind(this); this.awaitPts = awaitPts.bind(this);

View File

@ -87,29 +87,9 @@ export async function drawDimension() {
point.name = this.c_id point.name = this.c_id
point.userData.type = 'dimension' point.userData.type = 'dimension'
const updateDim = (c_id) => (ev_focus) => {
const value = ev_focus.target.textContent
console.log(value)
document.addEventListener('keydown', (e) => {
if (e.key == 'Enter') {
e.preventDefault()
const ent = this.constraints.get(c_id)
ent[1] = parseFloat(ev_focus.target.textContent)
this.constraints.set(c_id, ent)
this.updateOtherBuffers()
this.solve()
sc.render()
ev_focus.target.blur()
this.updateBoundingSpheres()
} else if (e.key == 'Escape') {
ev_focus.target.textContent = value
getSelection().empty()
ev_focus.target.blur()
}
})
}
point.label.addEventListener('focus', updateDim(this.c_id))
point.label.addEventListener('focus', this.updateDim(this.c_id))
@ -133,12 +113,39 @@ const p2 = new THREE.Vector2()
const p3 = new THREE.Vector2() const p3 = new THREE.Vector2()
let dir, hyp, proj, perp, p1e, p2e, nids, _p1, _p2; let dir, hyp, proj, perp, p1e, p2e, nids, _p1, _p2;
export function updateDim(c_id) {
return (ev_focus) => {
const value = ev_focus.target.textContent
document.addEventListener('keydown', (e) => {
if (e.key == 'Enter') {
e.preventDefault()
const ent = this.constraints.get(c_id)
ent[1] = parseFloat(ev_focus.target.textContent)
this.constraints.set(c_id, ent)
this.updateOtherBuffers()
this.solve()
sc.render()
ev_focus.target.blur()
this.updateBoundingSpheres()
} else if (e.key == 'Escape') {
ev_focus.target.textContent = value
getSelection().empty()
ev_focus.target.blur()
}
})
}
}
export function _onMoveDimension(point, line) { export function _onMoveDimension(point, line) {
nids = line.userData.nids nids = line.userData.nids
_p1 = this.obj3d.children[sketcher.objIdx.get(nids[0])].geometry.attributes.position.array _p1 = this.obj3d.children[this.objIdx.get(nids[0])].geometry.attributes.position.array
_p2 = this.obj3d.children[sketcher.objIdx.get(nids[1])].geometry.attributes.position.array _p2 = this.obj3d.children[this.objIdx.get(nids[1])].geometry.attributes.position.array
p1.set(_p1[0], _p1[1]) p1.set(_p1[0], _p1[1])
p2.set(_p2[0], _p2[1]) p2.set(_p2[0], _p2[1])
@ -163,27 +170,6 @@ export function _onMoveDimension(point, line) {
export function setDimLines() { export function setDimLines() {
const updateDim = (c_id) => (ev_focus) => {
const value = ev_focus.target.textContent
console.log(value)
document.addEventListener('keydown', (e) => {
if (e.key == 'Enter') {
e.preventDefault()
const ent = this.constraints.get(c_id)
ent[1] = parseFloat(ev_focus.target.textContent)
this.constraints.set(c_id, ent)
this.updateOtherBuffers()
this.solve()
sc.render()
ev_focus.target.blur()
this.updateBoundingSpheres()
} else if (e.key == 'Escape') {
ev_focus.target.textContent = value
getSelection().empty()
ev_focus.target.blur()
}
})
}
const restoreLabels = this.labelContainer.childElementCount == 0; const restoreLabels = this.labelContainer.childElementCount == 0;
@ -201,17 +187,14 @@ export function setDimLines() {
point.label.contentEditable = true; point.label.contentEditable = true;
this.labelContainer.append(point.label) this.labelContainer.append(point.label)
point.label.addEventListener('focus', this.updateDim(this.c_id))
point.label.addEventListener('focus', updateDim(this.c_id))
} }
nids = dims[i].userData.nids nids = dims[i].userData.nids
_p1 = this.obj3d.children[sketcher.objIdx.get(nids[0])].geometry.attributes.position.array _p1 = this.obj3d.children[this.objIdx.get(nids[0])].geometry.attributes.position.array
_p2 = this.obj3d.children[sketcher.objIdx.get(nids[1])].geometry.attributes.position.array _p2 = this.obj3d.children[this.objIdx.get(nids[1])].geometry.attributes.position.array
const offset = dims[i + 1].userData.offset const offset = dims[i + 1].userData.offset

View File

@ -13,35 +13,51 @@ export function onHover(e) {
); );
let hoverPts; let hoverPts;
let idx = []
if (this.obj3d.userData.type == 'sketch') { if (this.obj3d.userData.type == 'sketch') {
hoverPts = raycaster.intersectObjects([...this.obj3d.children[1].children, ...this.obj3d.children]) hoverPts = raycaster.intersectObjects([...this.obj3d.children[1].children, ...this.obj3d.children])
// if (!hoverPts.length) { if (hoverPts.length) {
// hoverPts = raycaster.intersectObjects(this.obj3d.children) let minDist = Infinity;
// } for (let i = 0; i < hoverPts.length; i++) {
} else { if (!hoverPts[i].distanceToRay) continue;
hoverPts = raycaster.intersectObjects(this.obj3d.children, true) if (hoverPts[i].distanceToRay < minDist - 0.0001) {
} minDist = hoverPts[i].distanceToRay
idx = [i]
// if (hoverDim.length) { } else if (Math.abs(hoverPts[i].distanceToRay - minDist) < 0.0001) {
// } idx.push(i)
}
let idx = []
if (hoverPts.length) {
let minDist = Infinity;
for (let i = 0; i < hoverPts.length; i++) {
if (!hoverPts[i].distanceToRay) continue;
if (hoverPts[i].distanceToRay < minDist - 0.0001) {
minDist = hoverPts[i].distanceToRay
idx = [i]
} else if (Math.abs(hoverPts[i].distanceToRay - minDist) < 0.0001) {
idx.push(i)
} }
// console.log(hoverPts, idx)
if (!idx.length) idx.push(0)
} }
// console.log(hoverPts, idx)
if (!idx.length) idx.push(0)
} else {
// hoverPts = raycaster.intersectObjects(this.obj3d.children)
hoverPts = raycaster.intersectObjects(this.obj3d.children,true)
// for (let i = 0; i < hoverPts.length; i++) {
// const obj = hoverPts[i].object
// if (obj.userData.type == "mesh" && obj.visible || obj.userData.type == "plane") {
// idx.push(i)
// }
// }
if (hoverPts.length) {
// console.log(hoverPts)
if (!idx.length) idx.push(0)
}
} }
if (idx.length) { // after filtering, hovered objs still exists if (idx.length) { // after filtering, hovered objs still exists
if (hoverPts[idx[0]].object != this.hovered[0]) { // if the previous hovered obj is not the same as current if (hoverPts[idx[0]].object != this.hovered[0]) { // if the previous hovered obj is not the same as current

View File

@ -1,11 +1,31 @@
fix css on design tree (a lot of work) \ fix css on design tree (a lot of work) \
clear dim on exit exit sketch / rehydrate when back or after loading clear dim on exit exit sketch / rehydrate when back or after loading \\\ done
boolean flesh out refresh / replace mesh
dimension to origin boolean flesh out refresh / replace mesh / delete mesh
- need to auto hide ( consume) when new boolean created
- create derived part using relationship as name
- sensible default names, like extrude 1, sketch 1, leverage react for this
- hidden bodies messes up hover highlight
extrude edit dialog. directio and magnitude
fix extrusion loop find fix extrusion loop find
dimension to origin
reattaching sketch reattaching sketch
file save file save
stl export stl export
angle angle
other constraints / sprite other constraints / sprite
finish mode messed up after restore