diff --git a/dist/app.css b/dist/app.css
new file mode 100644
index 0000000..66159fa
--- /dev/null
+++ b/dist/app.css
@@ -0,0 +1,185 @@
+/* @tailwind base; */
+
+.bg-gray-50 {
+ --tw-bg-opacity: 1;
+ background-color: rgba(249, 250, 251, var(--tw-bg-opacity));
+}
+
+.flex {
+ display: flex;
+}
+
+.table {
+ display: table;
+}
+
+.flex-col {
+ flex-direction: column;
+}
+
+.items-center {
+ align-items: center;
+}
+
+.justify-start {
+ justify-content: flex-start;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.justify-between {
+ justify-content: space-between;
+}
+
+.h-6 {
+ height: 1.5rem;
+}
+
+.text-lg {
+ font-size: 1.125rem;
+ line-height: 1.75rem;
+}
+
+.ml-2 {
+ margin-left: 0.5rem;
+}
+
+.p-1 {
+ padding: 0.25rem;
+}
+
+* {
+ --tw-shadow: 0 0 #0000;
+}
+
+* {
+ --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
+ --tw-ring-offset-width: 0px;
+ --tw-ring-offset-color: #fff;
+ --tw-ring-color: rgba(59, 130, 246, 0.5);
+ --tw-ring-offset-shadow: 0 0 #0000;
+ --tw-ring-shadow: 0 0 #0000;
+}
+
+.visible {
+ visibility: visible;
+}
+
+.w-6 {
+ width: 1.5rem;
+}
+
+.w-full {
+ width: 100%;
+}
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes ping {
+ 75%, 100% {
+ transform: scale(2);
+ opacity: 0;
+ }
+}
+
+@keyframes pulse {
+ 50% {
+ opacity: .5;
+ }
+}
+
+@keyframes bounce {
+ 0%, 100% {
+ transform: translateY(-25%);
+ animation-timing-function: cubic-bezier(0.8,0,1,1);
+ }
+
+ 50% {
+ transform: none;
+ animation-timing-function: cubic-bezier(0,0,0.2,1);
+ }
+}
+
+/* html, */
+
+body {
+ margin: 0;
+ height: 100%;
+ font-family: sans-serif;
+ overflow: hidden;
+ --topNavH: 36px;
+ --sideNavW: 200px;
+}
+
+#c {
+ position: absolute;
+ width: calc(100% - var(--sideNavW));
+ height: calc(100% - var(--topNavH));
+ bottom: 0;
+ right: 0;
+}
+
+.topNav {
+ position: absolute;
+ height: var(--topNavH);
+ left:0;
+ right:0;
+ top:0;
+}
+
+.sideNav {
+ position: absolute;
+ top: var(--topNavH);
+ left: 0;
+ bottom: 0;
+ width: var(--sideNavW);
+}
+
+#labels > div {
+ position: absolute;
+ border: solid 1px black;
+}
+
+.btn {
+ cursor: pointer;
+ --tw-bg-opacity: 1;
+ background-color: rgba(243, 244, 246, var(--tw-bg-opacity));
+}
+
+.btn:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgba(229, 231, 235, var(--tw-bg-opacity));
+}
+
+.btn {
+ fill: currentColor;
+ --tw-text-opacity: 1;
+ color: rgba(5, 150, 105, var(--tw-text-opacity));
+}
+
+.btn:hover {
+ --tw-text-opacity: 1;
+ color: rgba(4, 120, 87, var(--tw-text-opacity));
+}
+
+@media (min-width: 640px) {
+}
+
+@media (min-width: 768px) {
+}
+
+@media (min-width: 1024px) {
+}
+
+@media (min-width: 1280px) {
+}
+
+@media (min-width: 1536px) {
+}
+
diff --git a/dist/index.html b/dist/index.html
index 0a329c4..dc20e8a 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -21,7 +21,7 @@
- {/*
*/}
- {
- btnz.map(([Icon, fcn, txt], idx) => (
-
- ))
- }
-
-
-
- {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
-
-}
+document.addEventListener('DOMContentLoaded', () => {
+ ReactDOM.render(
, document.getElementById('react'));
+});
diff --git a/src/mouseEvents.js b/src/mouseEvents.js
index ceb4928..d5eabe6 100644
--- a/src/mouseEvents.js
+++ b/src/mouseEvents.js
@@ -43,6 +43,7 @@ export function onHover(e) {
if (hoverPts.length) {
+ console.log(hoverPts)
// for (let i = 0; i < hoverPts.length; i++) {
// const obj = hoverPts[i].object
// if (['point', 'plane'].includes(obj.userData.type)) {
@@ -50,7 +51,6 @@ export function onHover(e) {
// break;
// }
// }
- // console.log(hoverPts)
let minDist = Infinity;
diff --git a/src/navBar.jsx b/src/navBar.jsx
new file mode 100644
index 0000000..da17d4c
--- /dev/null
+++ b/src/navBar.jsx
@@ -0,0 +1,99 @@
+
+
+import React, { useEffect, useReducer} from 'react';
+
+import { useDispatch, useSelector } from 'react-redux'
+
+import { FaCube, FaEdit } from 'react-icons/fa'
+import { MdDone } from 'react-icons/md'
+import * as Icon from "./icons";
+
+
+
+export const NavBar = () => {
+ 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) => (
+
+ ))
+ }
+
+}
+
+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
+
+}
diff --git a/src/index.jsx b/src/reducer.js
similarity index 79%
rename from src/index.jsx
rename to src/reducer.js
index ea5ff59..f4a193a 100644
--- a/src/index.jsx
+++ b/src/reducer.js
@@ -1,18 +1,19 @@
-import ReactDOM from 'react-dom'
-import React from 'react'
-import { Root } from './app.jsx'
-import update from 'immutability-helper';
-
-import { createStore, applyMiddleware } from 'redux'
-import logger from 'redux-logger'
import { DepTree } from './depTree.mjs'
+import update from 'immutability-helper'
+export const preloadedState = {
+ treeEntries: {
+ byId: {},
+ allIds: [],
+ tree: {},
+ order: {},
+ },
+}
-
-function reducer(state = {}, action) {
+export function reducer(state = {}, action) {
switch (action.type) {
case 'rx-sketch':
return update(state, {
@@ -84,21 +85,3 @@ function reducer(state = {}, action) {
-const preloadedState = {
- treeEntries: {
- byId: {},
- allIds: [],
- tree: {},
- order: {},
- },
-}
-
-
-
-window.store = createStore(reducer, preloadedState, applyMiddleware(logger))
-
-
-document.addEventListener('DOMContentLoaded', () => {
- ReactDOM.render(
, document.getElementById('react'));
-});
-
diff --git a/src/treeEntry.jsx b/src/treeEntry.jsx
new file mode 100644
index 0000000..499d8de
--- /dev/null
+++ b/src/treeEntry.jsx
@@ -0,0 +1,112 @@
+
+
+import React, { useReducer } from 'react';
+import { useDispatch, useSelector } from 'react-redux'
+import { MdEdit, MdVisibilityOff, MdVisibility, MdDelete } from 'react-icons/md'
+
+
+export const Tree = () => {
+ const treeEntries = useSelector(state => state.treeEntries)
+
+ return
+ {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()
+ }}
+ >
+
+
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/webpack.common.js b/webpack.common.js
index db5858b..9d42bb3 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -4,7 +4,7 @@ const tailwindcss = require('tailwindcss')
module.exports = {
entry: {
- index: './src/index.jsx',
+ app: './src/app.jsx',
scene: './src/Scene.js',
},
output: {