import React, { useEffect, useReducer, useRef, useState } from 'react'; import './app.css' import { Provider, useDispatch, useSelector } from 'react-redux' import { FaCube, FaEdit } from 'react-icons/fa' import { MdEdit, MdDone, MdVisibilityOff, MdVisibility, MdDelete } from 'react-icons/md' import * as Icon from "./icons"; // import { color } from './shared' export const Root = ({ store }) => ( ); const App = () => { const dispatch = useDispatch() const treeEntries = useSelector(state => state.treeEntries) const activeSketchId = useSelector(state => state.activeSketchId) useEffect(() => { if (!activeSketchId) { sc.canvas.addEventListener('pointermove', sc.onHover) sc.canvas.addEventListener('pointerdown', sc.onPick) return () => { sc.canvas.removeEventListener('pointermove', sc.onHover) sc.canvas.removeEventListener('pointerdown', sc.onPick) } } }, [activeSketchId]) const btnz = [ activeSketchId ? [MdDone, () => { treeEntries.byId[activeSketchId].deactivate() sc.activeSketch = null // sc.activeDim = this.activeSketch.obj3d.children[1].children }, 'Finish'] : [FaEdit, sc.addSketch, 'Sketch'] , [FaCube, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Extrude'], [Icon.Union, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Union'], [Icon.Subtract, () => { if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) return // console.log('here') const [m1, m2] = sc.selected const mesh = subtract(m1, m2) console.log(mesh, 'meshres') dispatch({ type: 'rx-boolean', 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 <>
{/*
*/} { btnz.map(([Icon, fcn, txt], idx) => (
{txt}
)) }
{treeEntries.allIds.map((entId, idx) => ( ))}
} const TreeEntry = ({ entId }) => { const treeEntries = useSelector(state => state.treeEntries.byId) const dispatch = useDispatch() const activeSketchId = useSelector(state => state.activeSketchId) let obj3d, entry; entry = treeEntries[entId] if (entId[0] == "s") { obj3d = treeEntries[entId].obj3d } else { obj3d = treeEntries[entId] } const [_, forceUpdate] = useReducer(x => x + 1, 0); const vis = obj3d.visible return
{ if (entId[0] == 'm') { // entry.material.color.set(color.hover) sc.render() } }} onPointerLeave={() => { const obj = entry if (entId[0] == 'm' && !sc.selected.includes(obj)) { // obj.material.color.set(color.mesh) sc.render() } }} onPointerDown={() => { if (entId[0] == 'm') { sc.selected.push( entry ) sc.render() } }} > {entId}
{ activeSketchId && treeEntries[activeSketchId].deactivate() entry.activate() sc.clearSelection() sc.activeSketch = entry; }} >
{ dispatch({ type: 'delete-node', id: entId }) }} >
{ vis ?
{ obj3d.visible = false; sc.render() forceUpdate() }} >
:
{ obj3d.visible = true; sc.render() forceUpdate() }} >
}
} const subtract = (m1, m2) => { // //Create a bsp tree from each of the meshes // console.log(sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh'), "wtf") let bspA = BoolOp.fromMesh(m1) let bspB = BoolOp.fromMesh(m2) 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 let meshResult = BoolOp.toMesh(bspResult, m1.matrix, m1.material) meshResult.userData.type = 'mesh' meshResult.name = `${m1.name}-${m2.name}` sc.obj3d.add(meshResult) return meshResult }