semi working angle
parent
67d6bf8090
commit
8aeb5409c4
27
src/Scene.js
27
src/Scene.js
|
@ -111,8 +111,8 @@ export class Scene {
|
|||
helpersGroup.add(this.axes);
|
||||
|
||||
|
||||
const dist = 50
|
||||
const light1 = new THREE.PointLight(color.lighting, 0.7);
|
||||
const dist = 15
|
||||
const light1 = new THREE.PointLight(color.lighting, 0.6);
|
||||
light1.position.set(dist, dist, dist);
|
||||
helpersGroup.add(light1);
|
||||
const light2 = new THREE.PointLight(color.lighting, 0.6);
|
||||
|
@ -292,7 +292,7 @@ export class Scene {
|
|||
|
||||
}
|
||||
|
||||
subtract(m1, m2) {
|
||||
subtract(m1, m2, op) {
|
||||
let bspA = CSG.fromMesh(m1)
|
||||
let bspB = CSG.fromMesh(m2)
|
||||
m1.visible = false
|
||||
|
@ -302,13 +302,30 @@ export class Scene {
|
|||
|
||||
// // Subtract one bsp from the other via .subtract... other supported modes are .union and .intersect
|
||||
|
||||
let bspResult = bspA.subtract(bspB)
|
||||
let bspResult, opChar;
|
||||
switch (op) {
|
||||
case 's':
|
||||
bspResult = bspA.subtract(bspB)
|
||||
opChar = "-"
|
||||
break;
|
||||
case 'u':
|
||||
bspResult = bspA.union(bspB)
|
||||
opChar = "\u222a"
|
||||
break;
|
||||
case 'i':
|
||||
bspResult = bspA.intersect(bspB)
|
||||
opChar = "\u2229"
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// //Get the resulting mesh from the result bsp, and assign meshA.material to the resulting mesh
|
||||
|
||||
let mesh = CSG.toMesh(bspResult, m1.matrix, m1.material)
|
||||
mesh.userData.type = 'mesh'
|
||||
mesh.name = `${m1.name}-${m2.name}`
|
||||
|
||||
mesh.name = `(${m1.name}${opChar}${m2.name})`
|
||||
mesh.layers.enable(1)
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import { get3PtArc } from './drawArc'
|
|||
import { replacer, reviver } from './utils'
|
||||
import { AxesHelper } from './sketchAxes'
|
||||
import { drawDimension, _onMoveDimension, setDimLines, updateDim } from './drawDimension';
|
||||
import { drawAngle, _onMoveAngle, setAngLines, updateAng } from './drawAngle';
|
||||
|
||||
|
||||
|
||||
|
@ -128,9 +129,13 @@ class Sketch {
|
|||
this.drawOnClick2 = drawOnClick2.bind(this);
|
||||
|
||||
this.drawDimension = drawDimension.bind(this)
|
||||
this.drawAngle = drawAngle.bind(this)
|
||||
this._onMoveDimension = _onMoveDimension.bind(this)
|
||||
this._onMoveAngle = _onMoveAngle.bind(this)
|
||||
this.setDimLines = setDimLines.bind(this)
|
||||
this.setAngLines = setAngLines.bind(this)
|
||||
this.updateDim = updateDim.bind(this)
|
||||
this.updateAng = updateAng.bind(this)
|
||||
|
||||
this.awaitSelection = awaitSelection.bind(this);
|
||||
|
||||
|
@ -152,7 +157,7 @@ class Sketch {
|
|||
|
||||
this.setDimLines()
|
||||
|
||||
this.obj3d.traverse(e=>e.layers.enable(2))
|
||||
this.obj3d.traverse(e => e.layers.enable(2))
|
||||
this.obj3d.visible = true
|
||||
this.scene.axes.matrix = this.obj3d.matrix
|
||||
this.scene.axes.visible = true
|
||||
|
@ -168,7 +173,7 @@ class Sketch {
|
|||
this.store.dispatch({ type: 'exit-sketch' })
|
||||
this.labelContainer.innerHTML = ""
|
||||
this.obj3d.visible = false
|
||||
this.obj3d.traverse(e=>e.layers.disable(2))
|
||||
this.obj3d.traverse(e => e.layers.disable(2))
|
||||
this.scene.axes.visible = false
|
||||
this.scene.activeSketch = null
|
||||
}
|
||||
|
@ -221,6 +226,10 @@ class Sketch {
|
|||
this.drawDimension()
|
||||
this.mode = ""
|
||||
break;
|
||||
case 'q':
|
||||
this.drawAngle()
|
||||
this.mode = ""
|
||||
break;
|
||||
case 'p':
|
||||
this.canvas.addEventListener('pointerdown', this.drawOnClick1)
|
||||
this.mode = "point"
|
||||
|
@ -427,9 +436,9 @@ class Sketch {
|
|||
this.linkedObjs.size, links_buffer)
|
||||
|
||||
/*
|
||||
- loop to update all the children that are points
|
||||
- why +6? we skip first two triplets because it refers to a non-geometry children
|
||||
- we also sneak in updating lines children as well, by checking when ptsBuf[ptr] is NaN
|
||||
- loop to update all the children that are points
|
||||
- why +6? we skip first two triplets because it refers to a non-geometry children
|
||||
- we also sneak in updating lines children as well, by checking when ptsBuf[ptr] is NaN
|
||||
*/
|
||||
|
||||
for (let i = 3, ptr = (pts_buffer >> 2) + 9; i < this.obj3d.children.length; i += 1, ptr += 3) {
|
||||
|
@ -457,6 +466,7 @@ class Sketch {
|
|||
arcs were not updated in above loop, we go through all arcs linkedObjs
|
||||
and updated based on the control pts (which were updated in loop above)
|
||||
*/
|
||||
|
||||
for (let [k, obj] of this.linkedObjs) {
|
||||
if (obj[0] != 'arc') continue;
|
||||
const [p1, p2, c, arc] = obj[1].map(e => this.obj3d.children[this.objIdx.get(e)])
|
||||
|
@ -472,7 +482,8 @@ class Sketch {
|
|||
}
|
||||
|
||||
|
||||
this.setDimLines()
|
||||
// this.setDimLines()
|
||||
this.setAngLines()
|
||||
|
||||
this.obj3d.dispatchEvent({ type: 'change' })
|
||||
}
|
||||
|
|
|
@ -0,0 +1,395 @@
|
|||
import * as THREE from '../node_modules/three/src/Three';
|
||||
import { color } from './shared'
|
||||
|
||||
const lineMaterial = new THREE.LineBasicMaterial({
|
||||
linewidth: 2,
|
||||
color: color.dimension,
|
||||
})
|
||||
|
||||
|
||||
const pointMaterial = new THREE.PointsMaterial({
|
||||
color: color.dimension,
|
||||
size: 4,
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const divisions = 12
|
||||
|
||||
export async function drawAngle() {
|
||||
let selection = await this.awaitSelection({ line: 2 })
|
||||
|
||||
if (selection == null) return;
|
||||
|
||||
const line = new THREE.LineSegments(
|
||||
new THREE.BufferGeometry().setAttribute('position',
|
||||
new THREE.Float32BufferAttribute(Array((divisions + 2) * 2 * 3).fill(-0.001), 3)
|
||||
),
|
||||
lineMaterial.clone()
|
||||
);
|
||||
|
||||
const point = new THREE.Points(
|
||||
new THREE.BufferGeometry().setAttribute('position',
|
||||
new THREE.Float32BufferAttribute(3, 3)
|
||||
),
|
||||
pointMaterial.clone()
|
||||
)
|
||||
|
||||
line.userData.ids = selection.map(e => e.name)
|
||||
|
||||
line.layers.enable(2)
|
||||
point.layers.enable(2)
|
||||
|
||||
let angle = getAngle(selection)
|
||||
|
||||
|
||||
this.obj3d.children[1].add(line).add(point)
|
||||
|
||||
const onMove = this._onMoveAngle(point, line)
|
||||
|
||||
point.label = document.createElement('div');
|
||||
point.label.textContent = angle.toFixed(3);
|
||||
point.label.contentEditable = true;
|
||||
this.labelContainer.append(point.label)
|
||||
|
||||
let onEnd, onKey;
|
||||
let add = await new Promise((res) => {
|
||||
onEnd = (e) => res(true)
|
||||
onKey = (e) => e.key == 'Escape' && res(false)
|
||||
|
||||
this.canvas.addEventListener('pointermove', onMove)
|
||||
this.canvas.addEventListener('pointerdown', onEnd)
|
||||
window.addEventListener('keydown', onKey)
|
||||
})
|
||||
|
||||
this.canvas.removeEventListener('pointermove', onMove)
|
||||
this.canvas.removeEventListener('pointerdown', onEnd)
|
||||
window.removeEventListener('keydown', onKey)
|
||||
point.geometry.computeBoundingSphere()
|
||||
line.geometry.computeBoundingSphere()
|
||||
|
||||
if (add) {
|
||||
|
||||
this.constraints.set(++this.c_id,
|
||||
[
|
||||
'angle', angle,
|
||||
[-1, -1, selection[0].name, selection[1].name]
|
||||
]
|
||||
)
|
||||
|
||||
selection[0].userData.constraints.push(this.c_id)
|
||||
selection[1].userData.constraints.push(this.c_id)
|
||||
|
||||
this.updateOtherBuffers()
|
||||
|
||||
line.name = this.c_id
|
||||
line.userData.type = 'dimension'
|
||||
point.name = this.c_id
|
||||
point.userData.type = 'dimension'
|
||||
|
||||
point.label.addEventListener('focus', this.updateAng(this.c_id))
|
||||
|
||||
} else {
|
||||
|
||||
this.obj3d.children[1].children.splice(this.obj3d.children[1].length - 2, 2).forEach(
|
||||
e => {
|
||||
e.geometry.dispose()
|
||||
e.material.dispose()
|
||||
}
|
||||
)
|
||||
this.labelContainer.removeChild(this.labelContainer.lastChild);
|
||||
sc.render()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function updateAng(c_id) {
|
||||
return (ev_focus) => {
|
||||
let 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)
|
||||
value = ent[1]
|
||||
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()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let ids, _l1, _l2
|
||||
export function _onMoveAngle(point, line) {
|
||||
|
||||
ids = line.userData.ids
|
||||
|
||||
_l1 = this.obj3d.children[this.objIdx.get(ids[0])].geometry.attributes.position.array
|
||||
_l2 = this.obj3d.children[this.objIdx.get(ids[1])].geometry.attributes.position.array
|
||||
|
||||
let loc;
|
||||
|
||||
return (e) => {
|
||||
loc = this.getLocation(e)
|
||||
|
||||
p3.set(loc.x, loc.y)
|
||||
|
||||
update(
|
||||
line.geometry.attributes.position,
|
||||
point.geometry.attributes.position,
|
||||
_l1, _l2
|
||||
)
|
||||
|
||||
// point.userData.offset = tagOffset.toArray() // save offset vector from center
|
||||
point.userData.offset = tagOffset // save offset vector from center
|
||||
tagOffset = undefined
|
||||
|
||||
sc.render()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function setAngLines() {
|
||||
|
||||
const restoreLabels = this.labelContainer.childElementCount == 0;
|
||||
|
||||
const dims = this.obj3d.children[1].children
|
||||
|
||||
let point, dist;
|
||||
for (let i = 0; i < dims.length; i += 2) {
|
||||
if (restoreLabels) {
|
||||
point = dims[i + 1] // point node is at i+1
|
||||
dist = this.constraints.get(point.name)[1]
|
||||
point.label = document.createElement('div');
|
||||
point.label.textContent = dist.toFixed(3);
|
||||
point.label.contentEditable = true;
|
||||
this.labelContainer.append(point.label)
|
||||
|
||||
point.label.addEventListener('focus', this.updateAng(this.c_id))
|
||||
}
|
||||
|
||||
ids = dims[i].userData.ids
|
||||
|
||||
_l1 = this.obj3d.children[this.objIdx.get(ids[0])].geometry.attributes.position.array
|
||||
_l2 = this.obj3d.children[this.objIdx.get(ids[1])].geometry.attributes.position.array
|
||||
|
||||
|
||||
tagOffset = dims[i + 1].userData.offset
|
||||
|
||||
|
||||
|
||||
update(
|
||||
dims[i].geometry.attributes.position,
|
||||
dims[i + 1].geometry.attributes.position,
|
||||
_l1,
|
||||
_l2
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function findIntersection(q, s, p, r) {
|
||||
/*
|
||||
Based on: https://stackoverflow.com/questions/563198/
|
||||
|
||||
q+s p+r
|
||||
\/__________ q+u*s
|
||||
/\
|
||||
/ \
|
||||
p q
|
||||
|
||||
u = (q − p) × r / (r × s)
|
||||
when r × s = 0, the lines are either colinear or parallel
|
||||
|
||||
function returns u
|
||||
for "real" intersection to exist, 0<u<1
|
||||
*/
|
||||
const q_minus_p = q.clone().sub(p);
|
||||
const r_cross_s = r.cross(s);
|
||||
if (r_cross_s === 0) return null; //either colinear or parallel
|
||||
return q_minus_p.cross(r) / r_cross_s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
_l2:[x0,y0,z0,x1,y1,z1]
|
||||
/
|
||||
p3:tag-""/-.
|
||||
tagOffset[1]-->| \
|
||||
|__ . _|__ _l1:[x0,y0,z0,x1,y1,z1]
|
||||
tagOffset[0]----^ ^--center
|
||||
|
||||
vecArr = [
|
||||
0: _l1 origin
|
||||
1: _l1 disp
|
||||
2: _l2 origin
|
||||
3: _l2 disp
|
||||
4: center
|
||||
5: tag disp from center
|
||||
]
|
||||
*/
|
||||
|
||||
const vecArr = Array(6)
|
||||
for (var i = 0; i < vecArr.length; i++) vecArr[i] = new THREE.Vector2();
|
||||
const a = Array(3)
|
||||
const p3 = new THREE.Vector2()
|
||||
let tagOffset
|
||||
|
||||
const getAngle = (Obj3dLines) => {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const arr = Obj3dLines[i].geometry.attributes.position.array
|
||||
vecArr[2 * i].set(...arr.slice(0, 2))
|
||||
vecArr[2 * i + 1].set(arr[3] - arr[0], arr[4] - arr[1])
|
||||
}
|
||||
const a1 = Math.atan2(vecArr[1].y, vecArr[1].x)
|
||||
const a2 = Math.atan2(vecArr[3].y, vecArr[3].x)
|
||||
|
||||
let deltaAngle = Math.abs(a2 - a1)
|
||||
if (deltaAngle > Math.PI) {
|
||||
deltaAngle = Math.PI * 2 - deltaAngle
|
||||
}
|
||||
return deltaAngle / Math.PI * 180
|
||||
}
|
||||
|
||||
function update(linegeom, pointgeom, _l1, _l2) {
|
||||
|
||||
let i = 0;
|
||||
for (; i < 4;) {
|
||||
const arr = i == 0 ? _l1 : _l2
|
||||
vecArr[i++].set(arr[0], arr[1])
|
||||
vecArr[i++].set(arr[3] - arr[0], arr[4] - arr[1])
|
||||
}
|
||||
|
||||
const centerScalar = findIntersection(...vecArr.slice(0, 4))
|
||||
const center = vecArr[i++].addVectors(vecArr[0], vecArr[1].clone().multiplyScalar(centerScalar))
|
||||
|
||||
// tagOffset = vecArr[i++].subVectors(p3, center)
|
||||
|
||||
if (tagOffset === undefined) {
|
||||
tagOffset = vecArr[i++].subVectors(p3, center)
|
||||
// } else if (Array.isArray(tagOffset)) {
|
||||
// tagOffset = new THREE.Vector2(tagOffset[0],tagOffset[1])
|
||||
} else {
|
||||
p3.addVectors(center, tagOffset)
|
||||
}
|
||||
|
||||
// console.log(p3, center, 'vr')
|
||||
// console.log(vecArr, 'vecArr')
|
||||
|
||||
// console.log(tagOffset, xx)
|
||||
// console.log(tagOffset.length())
|
||||
const tagRadius = tagOffset.length()
|
||||
|
||||
/*
|
||||
if tag is more than 90 deg away from midline, we shift everything by 180
|
||||
|
||||
a: array that describes absolute angular position of angle start, angle end, and tag
|
||||
|
||||
a[2]:
|
||||
tag a[1]:angle end
|
||||
\ | /
|
||||
\ | /
|
||||
___\|/___ a[0]+dA/2:midline
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
a[0]:angle start
|
||||
*/
|
||||
|
||||
for (let j = 1, i = 0; j < vecArr.length; j += 2, i++) {
|
||||
a[i] = Math.atan2(vecArr[j].y, vecArr[j].x)
|
||||
}
|
||||
|
||||
let dA = unreflex(a[1] - a[0])
|
||||
|
||||
|
||||
let tagtoMidline = unreflex(a[2] - (a[0] + dA / 2))
|
||||
|
||||
let shift = Math.abs(tagtoMidline) < Math.PI / 2 ? 0 : Math.PI;
|
||||
|
||||
let tA1 = unreflex(a[2] - (a[0] + shift))
|
||||
let tA2 = unreflex(a[2] - (a[0] + dA + shift))
|
||||
|
||||
|
||||
let a1, deltaAngle;
|
||||
if (dA * tA1 < 0) {
|
||||
a1 = a[0] + tA1 + shift
|
||||
deltaAngle = dA - tA1
|
||||
} else if (dA * tA2 > 0) {
|
||||
a1 = a[0] + shift
|
||||
deltaAngle = dA + tA2
|
||||
} else {
|
||||
a1 = a[0] + shift
|
||||
deltaAngle = dA
|
||||
}
|
||||
|
||||
let points = linegeom.array
|
||||
|
||||
let d = 0;
|
||||
points[d++] = center.x + tagRadius * Math.cos(a1)
|
||||
points[d++] = center.y + tagRadius * Math.sin(a1)
|
||||
d++
|
||||
|
||||
const angle = a1 + (1 / divisions) * deltaAngle
|
||||
points[d++] = center.x + tagRadius * Math.cos(angle)
|
||||
points[d++] = center.y + tagRadius * Math.sin(angle)
|
||||
d++
|
||||
|
||||
for (i = 2; i <= divisions; i++) {
|
||||
points[d++] = points[d - 4]
|
||||
points[d++] = points[d - 4]
|
||||
d++
|
||||
const angle = a1 + (i / divisions) * deltaAngle
|
||||
points[d++] = center.x + tagRadius * Math.cos(angle)
|
||||
points[d++] = center.y + tagRadius * Math.sin(angle)
|
||||
d++
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
points[d++] = vecArr[2 * i].x
|
||||
points[d++] = vecArr[2 * i].y
|
||||
d++
|
||||
points[d++] = center.x + tagRadius * Math.cos(a[i] + shift)
|
||||
points[d++] = center.y + tagRadius * Math.sin(a[i] + shift)
|
||||
d++
|
||||
}
|
||||
|
||||
linegeom.needsUpdate = true;
|
||||
|
||||
pointgeom.array.set(p3.toArray())
|
||||
pointgeom.needsUpdate = true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
const twoPi = Math.PI * 2
|
||||
const negTwoPi = - Math.PI * 2
|
||||
const negPi = - Math.PI
|
||||
|
||||
function unreflex(angle) {
|
||||
if (angle > Math.PI) {
|
||||
angle = negTwoPi + angle
|
||||
} else if (angle < negPi) {
|
||||
angle = twoPi + angle
|
||||
}
|
||||
return angle
|
||||
}
|
|
@ -83,9 +83,38 @@ export function get3PtArc(p1, p2, c, divisions = n) {
|
|||
|
||||
const radius = Math.sqrt(v1[0] ** 2 + v1[1] ** 2)
|
||||
|
||||
|
||||
let deltaAngle = a2 - a1
|
||||
if (deltaAngle <=0) deltaAngle += Math.PI*2
|
||||
// console.log(deltaAngle)
|
||||
|
||||
// let deltaAngle = a2 - a1
|
||||
// if (deltaAngle > Math.PI ){
|
||||
// deltaAngle = - Math.PI*2 + deltaAngle
|
||||
// } else if (deltaAngle < -Math.PI) {
|
||||
// deltaAngle = Math.PI*2 + deltaAngle
|
||||
// }
|
||||
|
||||
// let deltaAngle = Math.abs(a2 - a1)
|
||||
// if (deltaAngle > Math.PI){
|
||||
// deltaAngle = Math.PI*2 - deltaAngle
|
||||
// }
|
||||
|
||||
|
||||
let points = new Float32Array((divisions + 1) * 3)
|
||||
|
||||
for (let d = 0; d <= divisions; d++) {
|
||||
const angle = a1 + (d / divisions) * deltaAngle;
|
||||
points[3 * d] = c[0] + radius * Math.cos(angle);
|
||||
points[3 * d + 1] = c[1] + radius * Math.sin(angle);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
|
||||
export function getAngleArc(a1, a2, c, radius, divisions = n) {
|
||||
|
||||
|
||||
let deltaAngle = a2 - a1
|
||||
|
||||
let points = new Float32Array((divisions + 1) * 3)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as THREE from '../node_modules/three/src/Three';
|
||||
import { color, ptObj } from './shared'
|
||||
import { color} from './shared'
|
||||
export function extrude(sketch) {
|
||||
|
||||
let constraints = sketch.constraints;
|
||||
|
@ -36,7 +36,7 @@ export function extrude(sketch) {
|
|||
)
|
||||
]
|
||||
if (d == -1 || d == node) continue;
|
||||
if (d == children[1]) {
|
||||
if (d == children[4]) {
|
||||
console.log('pair found')
|
||||
};
|
||||
findTouching(d)
|
||||
|
@ -52,7 +52,7 @@ export function extrude(sketch) {
|
|||
if (c == -1) continue;
|
||||
const d = children[objIdx.get(c)]
|
||||
if (d == node) continue;
|
||||
if (d == children[1]) {
|
||||
if (d == children[4]) {
|
||||
console.log('loop found')
|
||||
} else {
|
||||
if (!visited.has(d)) {
|
||||
|
|
|
@ -11,7 +11,7 @@ body {
|
|||
font-family: sans-serif;
|
||||
overflow: hidden;
|
||||
--topNavH: 48px;
|
||||
--sideNavW: 200px;
|
||||
--sideNavW: 240px;
|
||||
}
|
||||
|
||||
#c {
|
||||
|
|
|
@ -15,6 +15,20 @@ export const NavBar = () => {
|
|||
const treeEntries = useSelector(state => state.treeEntries)
|
||||
const activeSketchId = useSelector(state => state.treeEntries.activeSketchId)
|
||||
|
||||
|
||||
const boolOp = (code) => {
|
||||
if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) return
|
||||
const [m1, m2] = sc.selected
|
||||
const mesh = sc.subtract(m1, m2, code)
|
||||
dispatch({ type: 'rx-boolean', mesh, deps: [m1.name, m2.name] })
|
||||
sc.render()
|
||||
forceUpdate()
|
||||
}
|
||||
const extrude = () => {
|
||||
console.log(treeEntries.tree[activeSketchId])
|
||||
sc.extrude(treeEntries.byId[activeSketchId])
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!activeSketchId) {
|
||||
sc.canvas.addEventListener('pointermove', sc.onHover)
|
||||
|
@ -39,19 +53,10 @@ export const NavBar = () => {
|
|||
}, 'Finish'] :
|
||||
[FaEdit, sc.addSketch, 'Sketch [s]']
|
||||
,
|
||||
[FaCube, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Extrude [e]'],
|
||||
[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 = sc.subtract(m1, m2)
|
||||
|
||||
dispatch({ type: 'rx-boolean', mesh, deps: [m1.name, m2.name] })
|
||||
sc.render()
|
||||
forceUpdate()
|
||||
}, 'Subtract'],
|
||||
[Icon.Intersect, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Intersect'],
|
||||
[FaCube, extrude , 'Extrude [e]'],
|
||||
[Icon.Union, ()=>boolOp('u'), 'Union'],
|
||||
[Icon.Subtract, ()=>boolOp('s'), 'Subtract'],
|
||||
[Icon.Intersect, ()=>boolOp('i'), 'Intersect'],
|
||||
[Icon.Dimension, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Dimension [d]'],
|
||||
[Icon.Line, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Line [l]'],
|
||||
[Icon.Arc, () => sc.extrude(treeEntries.byId[activeSketchId]), 'Arc [a]'],
|
||||
|
|
|
@ -92,7 +92,7 @@ export function reducer(state = {}, action) {
|
|||
|
||||
|
||||
return update(state, {
|
||||
treeEntries: { $set: obj }
|
||||
treeEntries: { $merge: obj }
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -48,12 +48,10 @@ const TreeEntry = ({ entId }) => {
|
|||
const [_, forceUpdate] = useReducer(x => x + 1, 0);
|
||||
|
||||
|
||||
// const vis = obj3d.layers.mask & 1
|
||||
|
||||
return <div className='btn select-none flex justify-start w-full h-7 items-center text-sm'
|
||||
|
||||
onDoubleClick={() => {
|
||||
if (entId[0] == 's') {
|
||||
if (obj3d.userData.type == 'sketch') {
|
||||
activeSketchId && treeEntries[activeSketchId].deactivate()
|
||||
sketch.activate()
|
||||
sc.clearSelection()
|
||||
|
@ -67,14 +65,13 @@ const TreeEntry = ({ entId }) => {
|
|||
sc.render()
|
||||
}}
|
||||
onPointerLeave={() => {
|
||||
// console.log('activeid',activeSketchId,'visstate',visState)
|
||||
if (visible & entId[0] == 's') return
|
||||
if (visible & obj3d.userData.type == 'sketch') return
|
||||
if (sc.selected.includes(obj3d) || activeSketchId == obj3d.name) return
|
||||
sc.setHover(obj3d, 0)
|
||||
sc.render()
|
||||
}}
|
||||
onClick={() => {
|
||||
if (entId[0] == 'm') {
|
||||
if (obj3d.userData.type == 'mesh') {
|
||||
sc.selected.push(
|
||||
obj3d
|
||||
)
|
||||
|
|
14
todo.txt
14
todo.txt
|
@ -14,26 +14,30 @@ boolean flesh out refresh / replace mesh
|
|||
- consume skeches after extrude // done
|
||||
- selection hover disspates when rehovered //fixed
|
||||
- boolean unable to select click //fixed
|
||||
- hover sync between tree and work area // done, punt on stretch
|
||||
|
||||
|
||||
vertical // done
|
||||
horizontal // done
|
||||
- select sketch for extrusion, punt, leverage current sketch modality
|
||||
|
||||
|
||||
|
||||
- hover sync between tree and work area
|
||||
- select sketch for extrusion
|
||||
|
||||
auto update extrude
|
||||
extrude dialogue
|
||||
|
||||
loopfind
|
||||
button panel cleanup
|
||||
|
||||
file save, stl export
|
||||
|
||||
constriant buttons ,tangent, angle
|
||||
button panel cleanup
|
||||
|
||||
constraint angle
|
||||
3 pt arc
|
||||
|
||||
|
||||
constraint labels
|
||||
reattach sketch
|
||||
constraint labels, tangent
|
||||
auto snap
|
||||
tree ent renaming and better default names
|
Loading…
Reference in New Issue