Skip to content

Commit

Permalink
Move the history features to their own folder
Browse files Browse the repository at this point in the history
Signed-off-by: Dimitris Zervas <[email protected]>
  • Loading branch information
dzervas committed May 25, 2024
1 parent 40f6af3 commit 2cb9236
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 72 deletions.
33 changes: 6 additions & 27 deletions applications/web/src/routes/(CADmium)/FeatureHistory.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<script lang="ts">
import { workbench, realization } from "shared/stores"
import PointFeature from "./PointFeature.svelte"
import PlaneFeature from "./PlaneFeature.svelte"
import SketchFeature from "./SketchFeature.svelte"
import ExtrusionFeature from "./ExtrusionFeature.svelte"
import PointFeature from "./features/Point.svelte"
import PlaneFeature from "./features/Plane.svelte"
import SketchFeature from "./features/Sketch.svelte"
import ExtrusionFeature from "./features/Extrusion.svelte"
import SolidItem from "./SolidItem.svelte"
import { isPoint, isPlane, isExtrusion, isSketch } from "shared/projectUtils"
import type { SetCameraFocus } from "shared/types"
import FeatureInstance from "./features/FeatureInstance.svelte"
// prettier-ignore
const log = (function () { const context = "[FeatureHistory.svelte]"; const color="pink"; return Function.prototype.bind.call(console.log, console, `%c${context}`, `font-weight:bold;color:${color};`)})()
Expand Down Expand Up @@ -58,29 +59,7 @@
<div style="height:{Math.min(height, overallHeight - 12)}px" class="overflow-y-auto">
<div id="history" class="font-bold text-sm px-2 py-2">History ({history.length})</div>
{#each history as feature, featureIdx (feature.data.type + ":" + feature.unique_id)}
<div>
{#if isPoint(feature)}
<PointFeature name={feature.name} index={featureIdx} />
{:else if isPlane(feature)}
<PlaneFeature name={feature.name} index={featureIdx} plane={feature.data.plane} {setCameraFocus} />
{:else if isSketch(feature)}
<SketchFeature
name={feature.name}
index={featureIdx}
id={feature.unique_id}
plane_id={feature.data.plane_description.PlaneId}
/>
{:else if isExtrusion(feature)}
<ExtrusionFeature
name={feature.name}
index={featureIdx}
data={feature.data.extrusion}
id={feature.unique_id}
/>
{:else}
TODO: {feature.name} {feature.data.type}
{/if}
</div>
<FeatureInstance {feature} {featureIdx} />
{/each}
</div>
<!-- svelte-ignore a11y-no-static-element-interactions -->
Expand Down
150 changes: 150 additions & 0 deletions applications/web/src/routes/(CADmium)/NewArcTool.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<script lang="ts">
import { snapPoints, sketchTool, previewGeometry, currentlyMousedOver } from "shared/stores"
import { addCircleBetweenPoints, addPointToSketch } from "shared/projectUtils"
import { Vector3, type Vector2Like, type Vector3Like } from "three"
import type { PointLikeById, Point2D, PointsLikeById, ProjectToPlane } from "shared/types"
// prettier-ignore
const log = (function () { const context = "[NewArcTool.svelte]"; const color="gray"; return Function.prototype.bind.call(console.log, console, `%c${context}`, `font-weight:bold;color:${color};`)})()
export let pointsById: PointsLikeById
export let sketchIndex: string
export let active: boolean
export let projectToPlane: ProjectToPlane
// log("[props]", "pointsById:", pointsById, "sketchIndex:", sketchIndex, "active:", active)
let centerPoint: PointLikeById | null
$: if ($sketchTool !== "arc") centerPoint = null
// $: centerPoint, log("[centerPoint]", centerPoint)
function processPoint(point: PointLikeById) {
if (!centerPoint) {
// if there is no center point, set one
if (point.id) {
// nothing to do, the point exists!
// log('nothing to do the point exists!')
} else {
// again, don't actually DO anything yet to the sketch
point.id = null
}
centerPoint = point
} else {
// there WAS an center point, so we should create a circle!
// if the center point doesn't exist, then we should create a point
if (centerPoint.id === null) centerPoint.id = addPointToSketch(sketchIndex, centerPoint.twoD!, false)
if (point.id && centerPoint.id) {
// if the point exists, then we should create a circle between the two existing points
addCircleBetweenPoints(sketchIndex, centerPoint.id, point.id)
} else {
// if the point doesn't exist, then we should create a point and a circle
point.id = addPointToSketch(sketchIndex, point.twoD!, true)
}
if (point.id && centerPoint.id) addCircleBetweenPoints(sketchIndex, centerPoint.id, point.id)
centerPoint = null
}
}
export function click(_event: Event, projected: { twoD: Vector2Like; threeD: Vector3Like }) {
if ($snapPoints.length > 0) processPoint($snapPoints[0])
else {
let pt: PointLikeById = { twoD: projected.twoD, threeD: projected.threeD, id: null }
processPoint(pt)
}
}
// $: $snapPoints, log("[$snapPoints]", $snapPoints)
export function mouseMove(_event: Event, projected: { x: number; y: number }) {
// search through the existing points to see if we're close to one
// if we are, then we should snap to it
// TODO: in the future, we should also snap to the midpoints of lines
// and to the perimeters of circles and so on
// so these snap points do not necessarily correspond to actual points in the sketch
let snappedTo = null
for (const geom of $currentlyMousedOver) {
// log("[currentlyMousedOver geom]", geom)
if (geom.type === "point3D") {
const twoD = projectToPlane(new Vector3(geom.x, geom.y, geom.z))
// log("[projectToPlane twoD]", twoD)
const point = {
twoD: { x: twoD.x, y: twoD.y },
threeD: { x: geom.x, y: geom.y, z: geom.z },
id: null
}
snappedTo = point
}
if (geom.type === "point") {
// log("[currentlyMousedOver geom is type point]", geom)
const point = pointsById[geom.id]
// oops! point.twoD etc does not exist here, we have:
// const example = {
// type: "point",
// id: "1"
// }
function querySnapPoint(id: string | null) {
const points = $snapPoints.filter((point) => id && point.id === id)
return points.length > 0 ? points[0] : false
}
// see if we can retrieve it? unlikely
// log("[querySnapPoint found point:]", querySnapPoint(point?.id!))
// have not seen a successful query yet! sort it out with an if:
if (point.twoD && point.threeD && geom.id) snappedTo = { twoD: point.twoD, threeD: point.threeD, id: geom.id }
break // If there is a 2D point, prefer to use it rather than the 3D point
}
}
// if (snappedTo) log("[snappedTo]", snappedTo)
// only reset $snapPoints if something has changed
if (snappedTo) {
// @ts-ignore todo rework snapping
$snapPoints = [snappedTo] // todo all these different point representations need work!
} else {
if ($snapPoints.length > 0) {
$snapPoints = []
}
}
if (centerPoint) {
function calcDeltas(a: Vector2Like | Point2D | { x: number; y: number }, b: Vector2Like | undefined) {
const dx = a.x - b?.x!
const dy = a.y - b?.y!
return Math.hypot(dx, dy)
}
const radius = snappedTo ? calcDeltas(snappedTo.twoD, centerPoint.twoD) : calcDeltas(projected, centerPoint.twoD)
previewGeometry.set([
{
type: "circle",
center: centerPoint,
radius,
uuid: `circle-${centerPoint.twoD?.x}-${centerPoint.twoD?.y}-${radius}`
},
{
type: "point",
x: centerPoint.twoD?.x,
y: centerPoint.twoD?.y,
uuid: `point-${centerPoint.twoD?.x}-${centerPoint.twoD?.y}`
}
])
} else {
previewGeometry.set([])
}
}
export function onKeyDown(event: KeyboardEvent) {
if (!active) return
if (event.key === "Escape") {
previewGeometry.set([])
centerPoint = null
$sketchTool = "select"
}
}
</script>

<svelte:window on:keydown={onKeyDown} />
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@
// prettier-ignore
const log = (function () { const context = "[ExtrusionFeature.svelte]"; const color="gray"; return Function.prototype.bind.call(console.log, console, `%c${context}`, `font-weight:bold;color:${color};`)})()
export let name: string, index: number, id: string, data: ExtrusionData["data"]["extrusion"]
// $: data, log("[props]", "name:", name, "index:", index, "id:", id, "data:", data)
// $: data, log("[props]", "typeof id:", typeof id, "id:", id)
// $: data, log("[props]", "typeof data.face_ids[0]:", typeof data.face_ids[0], "data.face_ids:", data.face_ids)
export let name: string, unique_id: string, data: ExtrusionData["data"]["extrusion"], featureIdx: number
// coerce from number[] to string[] for frontend as we use strings for ids here
let faceIdsFromInputs = data.face_ids.sort().map((e) => e + "")
Expand Down Expand Up @@ -43,11 +39,11 @@
.filter((e) => e.type === "face")
.map((e) => e.id)
.sort()
updateExtrusion(id, data.sketch_id, length, faceIdsFromSelection)
updateExtrusion(unique_id, data.sketch_id, length, faceIdsFromSelection)
}
currentlySelected.subscribe((e) => {
if ($featureIndex !== index) return
if ($featureIndex !== featureIdx) return
// log("[$currentlySelected]", $currentlySelected)
// log("[$featureIndex]", typeof $featureIndex, $featureIndex)
Expand All @@ -72,7 +68,7 @@
const source = `${base}/actions/extrude_min.svg`
$: if ($featureIndex === index) {
$: if ($featureIndex === featureIdx) {
$selectingFor = ["face"]
$currentlySelected = faceIdsFromInputs.map((id) => ({ type: "face", id }))
// log("[$currentlySelected]", $currentlySelected)
Expand All @@ -84,15 +80,15 @@
role="button"
tabindex="0"
on:dblclick={() => {
if ($featureIndex === index) {
if ($featureIndex === featureIdx) {
closeAndRefresh()
} else {
$featureIndex = index
$featureIndex = featureIdx
// $selectingFor = []
}
}}
>
{#if $featureIndex < index}
{#if $featureIndex < featureIdx}
<img class="h-8 w-8 px-1 opacity-50" src={source} alt={name} />
<span class="italic opacity-50">{name}</span>
{:else}
Expand All @@ -101,7 +97,7 @@
{/if}
</div>

{#if $featureIndex === index}
{#if $featureIndex === featureIdx}
<div transition:slide={{ delay: 0, duration: 400, easing: quintOut, axis: "y" }}>
<form
on:submit|preventDefault={() => {
Expand Down Expand Up @@ -156,7 +152,7 @@
<button
class="flex-grow bg-sky-500 hover:bg-sky-700 text-white font-bold py-1.5 px-1 shadow"
on:click={() => {
renameStep(index, name)
renameStep(featureIdx, name)
}}>Done</button
>

Expand Down
6 changes: 6 additions & 0 deletions applications/web/src/routes/(CADmium)/features/Feature.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script lang="ts">
</script>

<div class="feature">
<slot></slot>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script lang="ts">
import * as AllFeatures from "./";
import type { HistoryStep } from "shared/types"
// prettier-ignore
const log = (function () { const context = "[FeatureInstance.svelte]"; const color="yellow"; return Function.prototype.bind.call(console.log, console, `%c${context}`, `font-weight:bold;color:${color};`)})()
export let feature: HistoryStep, featureIdx: number;
const FeatureComponent: ConstructorOfATypedSvelteComponent = AllFeatures[feature.data.type];
log("FeatureComponent:", FeatureComponent, "feature:", feature, "featureIdx:", featureIdx, "args:");
</script>

{#if FeatureComponent}
<!-- We're expanding the whole `feature` which will result in `<feature> was created with unknown prop '<x>'` -->
<svelte:component this={FeatureComponent} {...feature} {featureIdx} />
{:else}
<div>TODO: {feature.name} ({feature.data.type})</div>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
import { renameStep } from "shared/projectUtils"
import { workbenchIsStale, featureIndex } from "shared/stores"
import MagnifyingGlass from "phosphor-svelte/lib/MagnifyingGlass"
import type { Plane, SetCameraFocus } from "shared/types"
import type { Plane, PlaneData, SetCameraFocus } from "shared/types"
import { base } from "$app/paths"
// prettier-ignore
const log = (function () { const context = "[PlaneFeature.svelte]"; const color="gray"; return Function.prototype.bind.call(console.log, console, `%c${context}`, `font-weight:bold;color:${color};`)})()
export let name: string, index: number, plane: Plane, setCameraFocus: SetCameraFocus
// log("[props]", "name:", name, "index:", index, "plane:", plane, "setCameraFocus:", "(goTo: Vector3Like, lookAt: Vector3Like, up: Vector3Like) => void")
export let name: string, featureIdx: number//, data: PlaneData["data"]["plane"]
const source = `${base}/actions/plane_min.svg`
Expand All @@ -27,14 +26,14 @@
role="button"
tabindex="0"
on:dblclick={() => {
if ($featureIndex === index) {
if ($featureIndex === featureIdx) {
closeAndRefresh()
} else {
$featureIndex = index
$featureIndex = featureIdx
}
}}
>
{#if $featureIndex < index}
{#if $featureIndex < featureIdx}
<img class="h-8 w-8 px-1 opacity-50" src={source} alt={name} />
<span class="italic opacity-50">{name}</span>
{:else}
Expand All @@ -47,15 +46,16 @@
<div
class="ml-auto mr-2 bg-slate-100 px-1 py-1 rounded hover:bg-slate-200"
on:mousedown={() => {
setCameraFocus(plane.tertiary, plane.origin, plane.secondary)
// TODO: Pass setCameraFocus from FeatureInstance
// setCameraFocus(data.tertiary, data.origin, data.secondary)
// move camera to focus on plane
}}
>
<MagnifyingGlass weight="light" size="18px" />
</div>
</div>

{#if $featureIndex === index}
{#if $featureIndex === featureIdx}
<div transition:slide={{ delay: 0, duration: 400, easing: quintOut, axis: "y" }}>
<form
on:submit|preventDefault={() => {
Expand All @@ -79,7 +79,7 @@
<button
class="flex-grow bg-sky-500 hover:bg-sky-700 text-white font-bold py-1.5 px-1 shadow"
on:click={() => {
renameStep(index, name)
renameStep(featureIdx, name)
}}>Done</button
>

Expand Down
Loading

0 comments on commit 2cb9236

Please sign in to comment.