three.cad/src/app.jsx

215 lines
5.5 KiB
React
Raw Normal View History

2021-03-26 17:25:28 +08:00
2021-04-02 16:04:42 +08:00
import React, { useEffect, useReducer, useRef, useState } from 'react';
2021-04-01 16:20:50 +08:00
import './app.css'
2021-03-26 17:25:28 +08:00
2021-03-28 20:00:31 +08:00
import { Provider, useDispatch, useSelector } from 'react-redux'
2021-04-07 03:46:16 +08:00
2021-04-02 16:04:42 +08:00
import { FaCube, FaEdit } from 'react-icons/fa'
2021-04-06 12:52:19 +08:00
import { MdEdit, MdDone, MdVisibilityOff, MdVisibility, MdDelete } from 'react-icons/md'
2021-04-03 03:33:09 +08:00
import * as Icon from "./icons";
2021-04-07 03:46:16 +08:00
// import { color } from './shared'
2021-03-28 20:00:31 +08:00
2021-03-27 03:18:11 +08:00
export const Root = ({ store }) => (
2021-03-26 17:25:28 +08:00
<Provider store={store}>
2021-03-27 03:18:11 +08:00
<App></App>
2021-03-26 17:25:28 +08:00
</Provider>
);
2021-03-27 03:18:11 +08:00
2021-03-30 13:13:13 +08:00
2021-03-27 03:18:11 +08:00
const App = () => {
2021-03-28 20:00:31 +08:00
const dispatch = useDispatch()
2021-03-29 18:27:34 +08:00
const treeEntries = useSelector(state => state.treeEntries)
2021-04-06 12:52:19 +08:00
const activeSketchId = useSelector(state => state.activeSketchId)
2021-03-30 13:13:13 +08:00
2021-04-02 16:04:42 +08:00
2021-03-30 13:13:13 +08:00
useEffect(() => {
2021-04-06 12:52:19 +08:00
if (!activeSketchId) {
2021-03-31 07:20:24 +08:00
sc.canvas.addEventListener('pointermove', sc.onHover)
sc.canvas.addEventListener('pointerdown', sc.onPick)
2021-04-01 16:20:50 +08:00
return () => {
sc.canvas.removeEventListener('pointermove', sc.onHover)
sc.canvas.removeEventListener('pointerdown', sc.onPick)
2021-03-31 07:20:24 +08:00
}
2021-03-30 13:13:13 +08:00
}
2021-04-06 12:52:19 +08:00
}, [activeSketchId])
2021-03-27 03:18:11 +08:00
2021-03-28 20:00:31 +08:00
2021-04-02 08:19:14 +08:00
const btnz = [
2021-04-06 12:52:19 +08:00
activeSketchId ?
2021-04-05 11:52:17 +08:00
[MdDone, () => {
2021-04-06 12:52:19 +08:00
treeEntries.byId[activeSketchId].deactivate()
2021-04-05 11:52:17 +08:00
sc.activeSketch = null
// sc.activeDim = this.activeSketch.obj3d.children[1].children
}, 'Finish'] :
2021-04-02 16:04:42 +08:00
[FaEdit, sc.addSketch, 'Sketch']
2021-04-02 08:19:14 +08:00
,
2021-04-06 12:52:19 +08:00
[FaCube, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Extrude'],
[Icon.Union, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Union'],
2021-04-06 13:40:47 +08:00
[Icon.Subtract, () => {
2021-04-06 12:52:19 +08:00
if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) return
// console.log('here')
const [m1, m2] = sc.selected
2021-04-06 13:40:47 +08:00
const mesh = subtract(m1, m2)
console.log(mesh, 'meshres')
dispatch({ type: 'rx-boolean', mesh, deps: [m1.name, m2.name] })
2021-04-06 12:52:19 +08:00
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'],
2021-04-02 08:19:14 +08:00
]
2021-04-01 18:10:00 +08:00
2021-04-06 12:52:19 +08:00
const [_, forceUpdate] = useReducer(x => x + 1, 0);
2021-04-07 02:31:14 +08:00
return <>
<div className='absolute flex ml-auto mr-auto left-0 right-0 justify-center'>
{/* <div className='absolute flex justify-center'> */}
2021-04-06 13:40:47 +08:00
{
btnz.map(([Icon, fcn, txt], idx) => (
<div className="btn flex items-center justify-start p-1 text-lg" key={idx}
onClick={fcn}
>
<Icon className="w-6 h-6" />
<div className="ml-2">{txt}</div>
</div>
))
}
</div>
2021-04-02 08:19:14 +08:00
2021-04-07 02:31:14 +08:00
<div className='absolute left-0 top-36 w-40 flex flex-col'>
2021-04-06 12:52:19 +08:00
{treeEntries.allIds.map((entId, idx) => (
2021-04-02 16:04:42 +08:00
<TreeEntry key={idx} entId={entId} />
2021-03-28 20:00:31 +08:00
))}
</div>
2021-04-02 16:04:42 +08:00
2021-04-07 02:31:14 +08:00
</>
2021-04-02 16:04:42 +08:00
2021-03-28 20:00:31 +08:00
}
2021-04-02 16:04:42 +08:00
const TreeEntry = ({ entId }) => {
2021-04-06 12:52:19 +08:00
const treeEntries = useSelector(state => state.treeEntries.byId)
const dispatch = useDispatch()
2021-04-02 16:04:42 +08:00
2021-04-06 12:52:19 +08:00
const activeSketchId = useSelector(state => state.activeSketchId)
2021-04-02 16:04:42 +08:00
2021-04-03 03:33:09 +08:00
let obj3d, entry;
2021-04-05 11:52:17 +08:00
2021-04-03 03:33:09 +08:00
entry = treeEntries[entId]
if (entId[0] == "s") {
obj3d = treeEntries[entId].obj3d
2021-04-02 16:04:42 +08:00
} else {
2021-04-03 03:33:09 +08:00
obj3d = treeEntries[entId]
2021-04-02 16:04:42 +08:00
}
const [_, forceUpdate] = useReducer(x => x + 1, 0);
2021-04-03 03:33:09 +08:00
const vis = obj3d.visible
2021-04-02 16:04:42 +08:00
2021-04-05 16:05:53 +08:00
return <div className='bg-gray-50 flex justify-between w-full'>
2021-04-02 16:04:42 +08:00
<div className="btn"
onPointerEnter={() => {
if (entId[0] == 'm') {
2021-04-07 03:46:16 +08:00
// entry.material.color.set(color.hover)
2021-04-02 16:04:42 +08:00
sc.render()
}
}}
onPointerLeave={() => {
const obj = entry
if (entId[0] == 'm' && !sc.selected.includes(obj)) {
2021-04-07 03:46:16 +08:00
// obj.material.color.set(color.mesh)
2021-04-02 16:04:42 +08:00
sc.render()
}
}}
onPointerDown={() => {
if (entId[0] == 'm') {
sc.selected.push(
entry
)
sc.render()
}
}}
>
{entId}
</div>
2021-04-06 13:40:47 +08:00
<div className='flex'>
<div className='btn'
onClick={() => {
activeSketchId && treeEntries[activeSketchId].deactivate()
entry.activate()
2021-04-07 02:31:14 +08:00
sc.clearSelection()
2021-04-06 13:40:47 +08:00
sc.activeSketch = entry;
}}
>
<MdEdit />
</div>
<div className='btn'
onClick={() => {
dispatch({ type: 'delete-node', id: entId })
}}
>
<MdDelete />
</div>
{
vis ?
<div className='btn'
onClick={() => {
obj3d.visible = false;
sc.render()
forceUpdate()
}}
>
<MdVisibility />
</div>
:
<div className='btn'
onClick={() => {
obj3d.visible = true;
sc.render()
forceUpdate()
}}
>
<MdVisibilityOff />
</div>
}
</div>
2021-04-02 16:04:42 +08:00
</div>
}
2021-04-06 13:40:47 +08:00
const subtract = (m1, m2) => {
2021-04-03 03:33:09 +08:00
// //Create a bsp tree from each of the meshes
2021-04-05 11:52:17 +08:00
// console.log(sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh'), "wtf")
2021-04-06 12:52:19 +08:00
2021-04-03 03:33:09 +08:00
2021-04-05 11:52:17 +08:00
let bspA = BoolOp.fromMesh(m1)
let bspB = BoolOp.fromMesh(m2)
2021-04-03 03:33:09 +08:00
m1.visible = false
m2.visible = false
// // Subtract one bsp from the other via .subtract... other supported modes are .union and .intersect
let bspResult = bspA.subtract(bspB)
// //Get the resulting mesh from the result bsp, and assign meshA.material to the resulting mesh
2021-04-05 11:52:17 +08:00
let meshResult = BoolOp.toMesh(bspResult, m1.matrix, m1.material)
2021-04-06 12:52:19 +08:00
meshResult.userData.type = 'mesh'
2021-04-06 13:40:47 +08:00
meshResult.name = `${m1.name}-${m2.name}`
2021-04-03 03:33:09 +08:00
sc.obj3d.add(meshResult)
2021-04-06 12:52:19 +08:00
return meshResult
2021-04-03 03:33:09 +08:00
}
2021-04-02 16:04:42 +08:00