Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

web: reimplement new line tool state with stack instead of nested ifs #83

Merged
merged 4 commits into from
Jun 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 49 additions & 41 deletions applications/web/src/components/tools/NewLine.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,44 @@

export let pointsById: IDictionary<SketchPoint>, sketchIndex: string, active: boolean, projectToPlane: ProjectToPlane

// $: pointsById, log("[props]", pointsById, sketchIndex, active, projectToPlane)
let previousPoint: PointLikeById | null = null

let previousPoint: PointLikeById | null
let stack: PointLikeById[] = []

$: if ($sketchTool !== "line") previousPoint = null
$: if ($sketchTool !== "line") clearStack()

function processPoint(point: PointLikeById | null) {
if (!previousPoint && point) {
// if there is no anchor point, set one
if (point.id) {
// nothing to do, the point exists!
log("[processPoint] nothing to do the point exists!")
} else {
log("[processPoint] oh cool, creating point!")
point.id = null
}
} else {
// there WAS an anchor point, so we should create a line

// if the center point doesn't exist, then we should create a point
if (previousPoint?.id === null) previousPoint.id = addPointToSketch(sketchIndex, previousPoint?.twoD!, false)

if (point?.id) {
// if the point exists, then we should create a line
if (previousPoint?.id && point.id) addLineToSketch(sketchIndex, +previousPoint.id, +point.id)
previousPoint = null
return
} else {
// if the point doesn't exist, then we should create a point and a line
point!.id = addPointToSketch(sketchIndex, point!.twoD!, false)
addLineToSketch(sketchIndex, +previousPoint!.id!, +point!.id!)
}
}
// @ts-ignore todo rework points
function pushToStack(point: PointLikeById) {
// point should have the following properties:
// - twoD: an object with x and y properties representing the point in 2D space
// - threeD: an object with x, y, and z properties representing the point in 3D space
// - id: a string representing the id of the point in the sketch
// If the id is nullish we call addPointToSketch to create a new point in the sketch.
if (!point) return
point.id = point.id ?? addPointToSketch(sketchIndex, point.twoD, false)
stack.push(point)
}

function processPoint(point: PointLikeById) {
pushToStack(point)
previousPoint = point

switch (stack.length) {
case 0: // nothing to do, the stack is empty
break
case 1: // can't create a line with only one point!
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow that's so much clearer! great approach!

Copy link
Collaborator Author

@av8ta av8ta Jun 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Just had to write something my grug brain could understand haha

break
default:
const endPoint = popFromStack()
const startPoint = popFromStack()
addLineToSketch(sketchIndex, +startPoint.id, +endPoint.id)

// leave the current point on the stack in case we want to create another line from here
pushToStack(point)
// unless it's an earlier point, which means we're finished making lines, so we clear the stack
const isEarlierPoint = !!pointsById[point.id!]
if (isEarlierPoint) clearStack()
break
}
}

export function click(_event: Event, projected: Point) {
Expand All @@ -57,7 +60,6 @@
let snappedTo: PointLikeById | null = null

for (const geom of $currentlyMousedOver) {
// log("[geom of $currentlyMousedOver]", geom)
if (geom.type === "point3D") {
if (geom.x && geom.y && geom.z) {
const twoD = projectToPlane(new Vector3(geom.x, geom.y, geom.z))
Expand All @@ -66,19 +68,16 @@
threeD: {x: geom.x, y: geom.y, z: geom.z},
id: null,
} satisfies PointLikeById
// log("[point:PointLikeById]", point)
snappedTo = point
}
}
if (geom.type === "point") {
const point = pointsById[geom.id]
// log("[pointsById]", pointsById)
snappedTo = {
twoD: point.twoD,
threeD: point.threeD,
id: geom.id,
} satisfies PointLikeById
// log("[snappedTo]", snappedTo)
break // If there is a 2D point, prefer to use it rather than the 3D point
}
}
Expand All @@ -92,11 +91,10 @@

if (snappedTo) end = snappedTo

// prettier-ignore
const previewGeoms = [
{ type: "line", start: previousPoint, end: end, uuid: `line-${end.twoD!.x}-${end.twoD!.y}` },
{ type: "point", x: end.twoD!.x, y: end.twoD!.y, uuid: `point-${end.twoD!.x}-${end.twoD!.y}` }
] satisfies PreviewGeometry[]
{type: "line", start: previousPoint, end: end, uuid: `line-${end.twoD!.x}-${end.twoD!.y}`},
{type: "point", x: end.twoD!.x, y: end.twoD!.y, uuid: `point-${end.twoD!.x}-${end.twoD!.y}`},
] satisfies PreviewGeometry[]

if (previousPoint.id === null) {
const p = {
Expand All @@ -115,11 +113,21 @@
export function onKeyDown(event: KeyboardEvent) {
if (!active) return
if (event.key === "Escape") {
previewGeometry.set([])
previousPoint = null
clearStack()
$sketchTool = "select"
}
}

function clearStack() {
previousPoint = null
previewGeometry.set([])
snapPoints.set([])
stack = []
}

function popFromStack(): PointLikeById | undefined {
return stack.pop()
}
</script>

<svelte:window on:keydown={onKeyDown} />
Loading