diff --git a/src/Scene.js b/src/Scene.js index 88b7b45..a147fa3 100644 --- a/src/Scene.js +++ b/src/Scene.js @@ -5,7 +5,7 @@ import * as THREE from '../node_modules/three/src/Three'; // import { OrbitControls } from './utils/OrbitControls' import { TrackballControls } from './utils/trackball' -import { TwoDEnv } from './sketcher/TwoDEnv' +import { Sketch } from './sketcher/Sketch' import Stats from './utils/stats.module.js'; import { add3DPoint } from './datums' @@ -13,6 +13,7 @@ import { extrude } from './extrude' import { onHover, onPick } from './utils/mouseEvents'; import { _vec2, _vec3, color } from './utils/static' import { Vector3 } from 'three/src/Three'; +import {AxesHelper} from './utils/axes' import CSG from "./utils/three-csg.js" @@ -24,6 +25,7 @@ const eq = (a1, a2) => { return true } +window.loader = new THREE.ObjectLoader(); window.nid = 0 export class Scene { @@ -45,13 +47,13 @@ export class Scene { controls.target.set(0, 0, 0); controls.update(); - this.sketch = new THREE.Scene() + this.obj3d = new THREE.Scene() - this.sketch.background = new THREE.Color(0x888888); + this.obj3d.background = new THREE.Color(0x888888); const helpersGroup = new THREE.Group(); helpersGroup.name = "helpersGroup"; - this.sketch.add(helpersGroup); - const axesHelper = new THREE.AxesHelper(0.4); + this.obj3d.add(helpersGroup); + const axesHelper = new AxesHelper(0.4); helpersGroup.add(axesHelper); // console.log(color) @@ -85,13 +87,13 @@ export class Scene { const intensity = 1; const light1 = new THREE.DirectionalLight(color.lighting, intensity); light1.position.set(10, 10, 10); - this.sketch.add(light1); + this.obj3d.add(light1); const light2 = new THREE.DirectionalLight(color.lighting, intensity); light2.position.set(-10, -10, -5); - this.sketch.add(light2); + this.obj3d.add(light2); const ambient = new THREE.AmbientLight(color.lighting, intensity); - this.sketch.add(ambient); + this.obj3d.add(ambient); @@ -101,7 +103,7 @@ export class Scene { this.onHover = onHover.bind(this); this.onPick = onPick.bind(this); - this.sketch.addEventListener('change', this.render); + this.obj3d.addEventListener('change', this.render); controls.addEventListener('change', this.render); controls.addEventListener('start', this.render); window.addEventListener('resize', this.render); @@ -132,29 +134,37 @@ export class Scene { saveState() { localStorage.setItem( - 'sv', JSON.stringify([id, this.store.getState(), this.sketch.children.slice(4)]) + 'sv', JSON.stringify([nid, this.store.getState()]) ) } - loadState() { - - const [curId, state, treeItems] = JSON.parse( + loadState() { //uglyyy + const [curNid, state] = JSON.parse( localStorage.getItem('sv') ) - window.id = curId - this.store.dispatch({ type: 'restore-state', state }) + window.nid = curNid + const entries = state.treeEntries.byNid + for (let k in entries) { - for (let i = 0; i < treeItems.length; i++) { - const obj = loader.parse(treeItems[i]) - console.log(obj) - sc.add(obj) - // obj.visible = false + if (k[0] == 's') { + + entries[k].obj3d = loader.parse(entries[k].obj3d) + this.obj3d.add(entries[k].obj3d) + entries[k] = new Sketch(this.camera, this.canvas, this.store, state.treeEntries.byNid[k]) + entries[k].obj3d.addEventListener('change', this.render) // !! took 3 hours to realize + + } else if (k[0] == 'm') { + + entries[k] = loader.parse(state.treeEntries.byNid[k]) + this.obj3d.add(entries[k]) + + } } - + this.store.dispatch({ type: 'restore-state', state }) } } @@ -167,7 +177,7 @@ function render() { this.camera.right = canvas.clientWidth / canvas.clientHeight; this.camera.updateProjectionMatrix(); } - this.renderer.render(this.sketch, this.camera); + this.renderer.render(this.obj3d, this.camera); this.stats.end(); } @@ -201,17 +211,17 @@ async function addSketch() { } } - const sketcher = new TwoDEnv(this.camera, this.canvas, this.store) + const sketch = new Sketch(this.camera, this.canvas, this.store) if (references.length == 1 && references[0].name[0] == 'd') { - this.sketch.add(sketcher.sketch) - sketcher.sketch.matrix = references[0].matrix - sketcher.plane.applyMatrix4(sketcher.sketch.matrix) - sketcher.sketch.inverse = sketcher.sketch.matrix.clone().invert() + this.obj3d.add(sketch.obj3d) + sketch.obj3d.matrix = references[0].matrix + sketch.plane.applyMatrix4(sketch.obj3d.matrix) + sketch.obj3d.inverse = sketch.obj3d.matrix.clone().invert() } else if (references.length == 3) { - this.sketch.add(sketcher.sketch) - sketcher.align( + this.obj3d.add(sketch.obj3d) + sketch.align( ...references.map( el => new Vector3(...el.geometry.attributes.position.array).applyMatrix4(el.matrixWorld) ) @@ -222,16 +232,15 @@ async function addSketch() { return; } - sketcher.activate() - sketcher.sketch.addEventListener('change', this.render); + sketch.activate() + sketch.obj3d.addEventListener('change', this.render); this.render() - this.store.dispatch({ type: 'rx-sketch', obj: sketcher }) + this.store.dispatch({ type: 'rx-sketch', obj: sketch }) - window.sketcher = sketcher } window.sc = new Scene(store); -window.loader = new THREE.ObjectLoader(); + diff --git a/src/app.jsx b/src/app.jsx index f99a7a9..8edac99 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -18,7 +18,7 @@ export const Root = ({ store }) => ( const App = () => { const dispatch = useDispatch() const treeEntries = useSelector(state => state.treeEntries) - const activeSketch = useSelector(state => state.activeSketch) + const activeSketchNid = useSelector(state => state.activeSketchNid) // const [state, setState] = useState('x') // useEffect(()=>{ @@ -26,7 +26,7 @@ const App = () => { // },[state]) useEffect(() => { - if (!activeSketch) { + if (!activeSketchNid) { sc.canvas.addEventListener('pointermove', sc.onHover) sc.canvas.addEventListener('pointerdown', sc.onPick) return () => { @@ -34,29 +34,29 @@ const App = () => { sc.canvas.removeEventListener('pointerdown', sc.onPick) } } - }, [activeSketch]) + }, [activeSketchNid]) return <>
- {activeSketch ? - : } - + {/* */}
- { treeEntries.allIds.map((entId, idx) => ( + { treeEntries.allNids.map((entId, idx) => (
{ - if (activeSketch) { - activeSketch.deactivate() + if (activeSketchNid) { + treeEntries.byNid[activeSketchNid].deactivate() } - treeEntries.byId[entId].activate() + treeEntries.byNid[entId].activate() } } >{entId}
diff --git a/src/datums.js b/src/datums.js index bf36c7e..c036132 100644 --- a/src/datums.js +++ b/src/datums.js @@ -23,7 +23,7 @@ export function add3DPoint(e) { ); // const hoverPts = this.raycaster.intersectObjects(this.sketch.children) - const hoverPts = this.raycaster.intersectObjects(this.sketcher.children) + const hoverPts = this.raycaster.intersectObjects(this.sketch.children) console.log(hoverPts) diff --git a/src/extrude.js b/src/extrude.js index c6b3b81..4c6b045 100644 --- a/src/extrude.js +++ b/src/extrude.js @@ -4,7 +4,7 @@ export function extrude(sketch) { let constraints = sketch.constraints; let linkedObjs = sketch.linkedObjs; - let children = sketch.sketch.children; + let children = sketch.obj3d.children; let objIdx = sketch.objIdx; let visited = new Set() let v2s = [] @@ -89,8 +89,8 @@ export function extrude(sketch) { mesh.matrixAutoUpdate = false; - mesh.matrix.multiply(sketch.sketch.matrix) - this.sketch.add(mesh) + mesh.matrix.multiply(sketch.obj3d.matrix) + this.obj3d.add(mesh) this.render() diff --git a/src/index.js b/src/index.js index d8b2b89..b3f5027 100644 --- a/src/index.js +++ b/src/index.js @@ -15,28 +15,29 @@ function reducer(state = {}, action) { return { ...state, treeEntries: { - byId: { ...state.treeEntries.byId, [action.obj.sketch.name]: action.obj }, - allIds: [...state.treeEntries.allIds, action.obj.sketch.name] + byNid: { ...state.treeEntries.byNid, [action.obj.obj3d.name]: action.obj }, + allNids: [...state.treeEntries.allNids, action.obj.obj3d.name] } } case 'set-active-sketch': + console.log('action',action) return { - ...state, activeSketch: action.sketch + ...state, activeSketchNid: action.sketch } case 'exit-sketch': return { - ...state, activeSketch: '' + ...state, activeSketchNid: '' } case 'rx-extrusion': return { ...state, treeEntries: { - byId: { ...state.treeEntries.byId, [action.mesh.name]: action.mesh }, - allIds: [...state.treeEntries.allIds, action.mesh.name] + byNid: { ...state.treeEntries.byNid, [action.mesh.name]: action.mesh }, + allNids: [...state.treeEntries.allNids, action.mesh.name] }, mesh2sketch: { ...state.mesh2sketch, - [action.sketch.sketch.name]: action.mesh.name + [action.sketch.obj3d.name]: action.mesh.name } } case 'restore-state': @@ -51,8 +52,8 @@ function reducer(state = {}, action) { const preloadedState = { treeEntries: { - byId: {}, - allIds: [] + byNid: {}, + allNids: [] } } diff --git a/src/sketcher/TwoDEnv.js b/src/sketcher/Sketch.js similarity index 77% rename from src/sketcher/TwoDEnv.js rename to src/sketcher/Sketch.js index 162b558..ed78a8d 100644 --- a/src/sketcher/TwoDEnv.js +++ b/src/sketcher/Sketch.js @@ -8,60 +8,100 @@ import { addDimension, setCoincident } from './constraintEvents' import { get3PtArc } from './drawArc' import { _vec2, _vec3, raycaster } from '../utils/static' import { replacer, reviver } from '../utils/mapJSONReplacer' +import {AxesHelper} from '../utils/axes' -class TwoDEnv { +class Sketch { - constructor(camera, canvas, store, sketch) { + constructor(camera, canvas, store, preload) { + + + // [0]:x, [1]:y, [2]:z + this.ptsBuf = new Float32Array(this.max_pts * 3).fill(NaN) + + // [0]:type, [1]:pt1, [2]:pt2, [3]:pt3, [4]:pt4 + this.linksBuf = new Float32Array(this.max_links * 5).fill(NaN) + + // [0]:type, [1]:val, [2]:pt1, [3]:pt2, [4]:lk1, [5]:lk2 + this.constraintsBuf = new Float32Array(this.max_constraints * 6).fill(NaN) + + + this.plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0); + + if (preload === undefined) { + + this.obj3d = new THREE.Group() + this.obj3d.name = "s" + nid++ + this.obj3d.matrixAutoUpdate = false; + + this.objIdx = new Map() + + this.linkedObjs = new Map() + this.l_id = 0; + + this.constraints = new Map() + this.c_id = 0; + + this.sub = new THREE.Group(); + this.obj3d.add(this.sub); + const axesHelper = new AxesHelper(2); + this.sub.add(axesHelper); - if (sketch === undefined) { - this.sketch = new THREE.Group() - this.sketch.name = "s" + nid++ - this.sketch.matrixAutoUpdate = false; } else { - this.sketch = sketch + + + this.obj3d = preload.obj3d + this.obj3d.inverse = preload.obj3d.matrix.clone().invert() + + this.objIdx = JSON.parse(preload.objIdx, reviver) + + this.linkedObjs = JSON.parse(preload.linkedObjs, reviver) + this.l_id = preload.l_id; + + this.constraints = JSON.parse(preload.constraints, reviver) + this.c_id = preload.c_id; + + + this.updatePointsBuffer() + this.updateOtherBuffers() + + this.plane.applyMatrix4(this.obj3d.matrix) } this.camera = camera; this.canvas = canvas; this.store = store; - this.sub = new THREE.Group(); - this.sketch.add(this.sub); - const axesHelper = new THREE.AxesHelper(2); - this.sub.add(axesHelper); - this.plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0); - // [0]:x, [1]:y, [2]:z - this.objIdx = new Map() - this.ptsBuf = new Float32Array(this.max_pts * 3).fill(NaN) - - // [0]:type, [1]:pt1, [2]:pt2, [3]:pt3, [4]:pt4 - this.linkedObjs = new Map() - this.l_id = 0; - this.linksBuf = new Float32Array(this.max_links * 5).fill(NaN) - - // [0]:type, [1]:val, [2]:pt1, [3]:pt2, [4]:lk1, [5]:lk2 - this.constraints = new Map() - this.c_id = 0; - this.constraintsBuf = new Float32Array(this.max_constraints * 6).fill(NaN) this.bindHandlers() - - // this.selected = new Set() this.selected = [] this.hovered = [] this.mode = "" this.subsequent = false; } + toJSON() { + return { + obj3d: this.obj3d, + + objIdx: JSON.stringify(this.objIdx, replacer), + + linkedObjs: JSON.stringify(this.linkedObjs, replacer), + l_id: this.l_id, + + constraints: JSON.stringify(this.constraints, replacer), + c_id: this.c_id, + } + } + bindHandlers() { this.drawOnClick1 = drawOnClick1.bind(this); @@ -81,7 +121,9 @@ class TwoDEnv { window.addEventListener('keydown', this.onKeyPress) this.canvas.addEventListener('pointerdown', this.onPick) this.canvas.addEventListener('pointermove', this.onHover) - this.store.dispatch({ type: 'set-active-sketch', sketch: this }) + this.store.dispatch({ type: 'set-active-sketch', sketch: this.obj3d.name }) + + window.sketcher = this } deactivate() { @@ -103,16 +145,16 @@ class TwoDEnv { te[1] = _x.y; te[5] = _y.y; te[9] = _z.y; te[2] = _x.z; te[6] = _y.z; te[10] = _z.z; - this.sketch.quaternion.setFromRotationMatrix(_m1); - const parent = this.sketch.parent; + this.obj3d.quaternion.setFromRotationMatrix(_m1); + const parent = this.obj3d.parent; _m1.extractRotation(parent.matrixWorld); _q1.setFromRotationMatrix(_m1); - this.sketch.quaternion.premultiply(_q1.invert()); - this.sketch.updateMatrix(); - this.sketch.matrix.setPosition(origin) + this.obj3d.quaternion.premultiply(_q1.invert()); + this.obj3d.updateMatrix(); + this.obj3d.matrix.setPosition(origin) - this.plane.applyMatrix4(this.sketch.matrix) - this.sketch.inverse = this.sketch.matrix.clone().invert() + this.plane.applyMatrix4(this.obj3d.matrix) + this.obj3d.inverse = this.obj3d.matrix.clone().invert() } @@ -173,7 +215,7 @@ class TwoDEnv { this.updateOtherBuffers() this.selected = [] - this.sketch.dispatchEvent({ type: 'change' }) + this.obj3d.dispatchEvent({ type: 'change' }) } delete(obj) { @@ -184,7 +226,7 @@ class TwoDEnv { let i = this.objIdx.get(link[0]) || this.updatePoint // hacky, see drawEvent.js for updatePoint def for (let j = 0; j < link.length; j++) { - const obj = this.sketch.children[i + j] + const obj = this.obj3d.children[i + j] obj.geometry.dispose() obj.material.dispose() @@ -193,7 +235,7 @@ class TwoDEnv { } } - this.sketch.children.splice(i, link.length) + this.obj3d.children.splice(i, link.length) this.linkedObjs.delete(obj.userData.l_id) @@ -204,7 +246,7 @@ class TwoDEnv { deleteConstraints(c_id) { for (let idx of this.constraints.get(c_id)[2]) { ////////// if (idx == -1) continue - const ob = this.sketch.children[this.objIdx.get(idx)] + const ob = this.obj3d.children[this.objIdx.get(idx)] if (ob) { // ob.constraints.delete(c_id) ob.userData.constraints.splice(ob.userData.constraints.indexOf(c_id), 1) @@ -242,8 +284,8 @@ class TwoDEnv { updatePointsBuffer(startingIdx = 0) { - for (let i = startingIdx; i < this.sketch.children.length; i++) { - const obj = this.sketch.children[i] + for (let i = startingIdx; i < this.obj3d.children.length; i++) { + const obj = this.obj3d.children[i] this.objIdx.set(obj.name, i) if (obj.type == "Points") { this.ptsBuf.set(obj.geometry.attributes.position.array, 3 * i) @@ -260,7 +302,7 @@ class TwoDEnv { this.camera ); - raycaster.ray.intersectPlane(this.plane, _vec3).applyMatrix4(this.sketch.inverse) + raycaster.ray.intersectPlane(this.plane, _vec3).applyMatrix4(this.obj3d.inverse) return _vec3.toArray() } @@ -280,7 +322,7 @@ class TwoDEnv { Module.HEAPF32.set(this.linksBuf, links_buffer >> 2) Module["_solver"]( - this.sketch.children.length, pts_buffer, + this.obj3d.children.length, pts_buffer, this.constraints.size, constraints_buffer, this.linkedObjs.size, links_buffer) @@ -290,9 +332,10 @@ class TwoDEnv { - we also sneak in updating lines children as well, by checking when ptsBuf[ptr] is NaN */ - for (let i = 1, ptr = (pts_buffer >> 2) + 3; i < this.sketch.children.length; i += 1, ptr += 3) { + for (let i = 1, ptr = (pts_buffer >> 2) + 3; i < this.obj3d.children.length; i += 1, ptr += 3) { + // for (let i = 0, ptr = (pts_buffer >> 2) + 3; i < this.obj3d.children.length; i += 1, ptr += 3) { - const pos = this.sketch.children[i].geometry.attributes.position; + const pos = this.obj3d.children[i].geometry.attributes.position; if (isNaN(Module.HEAPF32[ptr])) { pos.array[0] = Module.HEAPF32[ptr - 6] pos.array[1] = Module.HEAPF32[ptr - 5] @@ -316,7 +359,7 @@ class TwoDEnv { */ for (let [k, obj] of this.linkedObjs) { if (obj[0] != 'arc') continue; - const [p1, p2, c, arc] = obj[1].map(e => this.sketch.children[this.objIdx.get(e)]) + const [p1, p2, c, arc] = obj[1].map(e => this.obj3d.children[this.objIdx.get(e)]) const points = get3PtArc( p1.geometry.attributes.position.array, @@ -329,19 +372,10 @@ class TwoDEnv { } - this.sketch.dispatchEvent({ type: 'change' }) + this.obj3d.dispatchEvent({ type: 'change' }) } - toJSON() { - this.userData = { - constraints: JSON.stringify(this.constraints, replacer), - linkedObjs: JSON.stringify(this.linkedObjs, replacer), - objIdx: JSON.stringify(this.objIdx, replacer), - c_id: this.c_id, - l_id: this.l_id - } - return super.toJSON() - } + } @@ -352,7 +386,7 @@ const _y = new THREE.Vector3(); const _z = new THREE.Vector3(); -Object.assign(TwoDEnv.prototype, +Object.assign(Sketch.prototype, { linkNum: { 'line': 0, @@ -370,4 +404,4 @@ Object.assign(TwoDEnv.prototype, -export { TwoDEnv } \ No newline at end of file +export { Sketch } \ No newline at end of file diff --git a/src/sketcher/constraintEvents.js b/src/sketcher/constraintEvents.js index bdaef91..b65fb02 100644 --- a/src/sketcher/constraintEvents.js +++ b/src/sketcher/constraintEvents.js @@ -48,5 +48,5 @@ export function setCoincident() { obj.material.color.set(0x555555) } this.selected = [] - this.sketch.dispatchEvent({ type: 'change' }) + this.obj3d.dispatchEvent({ type: 'change' }) } diff --git a/src/sketcher/drawEvents.js b/src/sketcher/drawEvents.js index 025ac2f..8a96b25 100644 --- a/src/sketcher/drawEvents.js +++ b/src/sketcher/drawEvents.js @@ -13,8 +13,8 @@ export function drawOnClick1(e) { this.toPush = drawArc(mouseLoc) } - this.updatePoint = this.sketch.children.length - this.sketch.add(...this.toPush) + this.updatePoint = this.obj3d.children.length + this.obj3d.add(...this.toPush) this.linkedObjs.set(this.l_id, [this.mode, this.toPush.map(e=>e.name)]) for (let obj of this.toPush) { @@ -36,7 +36,7 @@ export function drawPreClick2(e) { drawArc2(mouseLoc, this.toPush) } - this.sketch.dispatchEvent({ type: 'change' }) + this.obj3d.dispatchEvent({ type: 'change' }) } export function drawOnClick2(e) { @@ -65,9 +65,9 @@ export function drawClear() { this.canvas.removeEventListener('pointermove', this.drawPreClick2); this.canvas.removeEventListener('pointerdown', this.drawOnClick2); - this.delete(this.sketch.children[this.updatePoint]) + this.delete(this.obj3d.children[this.updatePoint]) - this.sketch.dispatchEvent({ type: 'change' }) + this.obj3d.dispatchEvent({ type: 'change' }) this.subsequent = false } } diff --git a/src/sketcher/drawLine.js b/src/sketcher/drawLine.js index bd18c3c..f46daaf 100644 --- a/src/sketcher/drawLine.js +++ b/src/sketcher/drawLine.js @@ -26,12 +26,12 @@ export function drawLine(mouseLoc) { this.constraints.set(++this.c_id, [ 'coincident', -1, - [this.sketch.children[this.sketch.children.length - 2].name, p1.name, -1, -1] + [this.obj3d.children[this.obj3d.children.length - 2].name, p1.name, -1, -1] ] ) p1.userData.constraints.push(this.c_id) - this.sketch.children[this.sketch.children.length - 2].userData.constraints.push(this.c_id) + this.obj3d.children[this.obj3d.children.length - 2].userData.constraints.push(this.c_id) } diff --git a/src/utils/axes.js b/src/utils/axes.js new file mode 100644 index 0000000..fe1bc15 --- /dev/null +++ b/src/utils/axes.js @@ -0,0 +1,39 @@ +// import { LineSegments } from '../objects/LineSegments.js'; +// import { LineBasicMaterial } from '../materials/LineBasicMaterial.js'; +// import { Float32BufferAttribute } from '../core/BufferAttribute.js'; +// import { BufferGeometry } from '../core/BufferGeometry.js'; + +import {LineSegments, LineBasicMaterial, Float32BufferAttribute, BufferGeometry} from 'three/src/Three' + +class AxesHelper extends LineSegments { + + constructor( size = 1 ) { + + const vertices = [ + 0, 0, 0, size, 0, 0, + 0, 0, 0, 0, size, 0, + 0, 0, 0, 0, 0, size + ]; + + const colors = [ + 1, 0, 0, 1, 0.6, 0, + 0, 1, 0, 0.6, 1, 0, + 0, 0, 1, 0, 0.6, 1 + ]; + + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + + const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); + + super( geometry, material ); + + // this.type = 'AxesHelper'; + + } + +} + + +export { AxesHelper }; diff --git a/src/utils/mouseEvents.js b/src/utils/mouseEvents.js index 833617a..d7b0c7a 100644 --- a/src/utils/mouseEvents.js +++ b/src/utils/mouseEvents.js @@ -13,10 +13,10 @@ export function onHover(e) { ); let hoverPts; - if (this.sketch.name[0]=='s') { - hoverPts = raycaster.intersectObjects(this.sketch.children) + if (this.obj3d.name[0]=='s') { + hoverPts = raycaster.intersectObjects(this.obj3d.children) } else { - hoverPts = raycaster.intersectObjects(this.sketch.children, true) + hoverPts = raycaster.intersectObjects(this.obj3d.children, true) } let idx = [] @@ -51,7 +51,7 @@ export function onHover(e) { this.hovered[this.hovered.length - 1].material.color.set(color.hover) // console.log('render1') - this.sketch.dispatchEvent({ type: 'change' }) + this.obj3d.dispatchEvent({ type: 'change' }) } } else { if (this.hovered.length) { @@ -63,7 +63,7 @@ export function onHover(e) { this.hovered = [] // console.log('render2') - this.sketch.dispatchEvent({ type: 'change' }) + this.obj3d.dispatchEvent({ type: 'change' }) } } } @@ -85,7 +85,7 @@ export function onPick(e) { // obj.material.color.set(0x555555) obj.material.color.set(color[obj.name[0]]) } - this.sketch.dispatchEvent({ type: 'change' }) + this.obj3d.dispatchEvent({ type: 'change' }) this.selected = [] } } @@ -102,7 +102,7 @@ export function onDrag(e) { } this.solve() - this.sketch.dispatchEvent({ type: 'change' }) + this.obj3d.dispatchEvent({ type: 'change' }) }