Compare commits
6 Commits
move-tests
...
jtran/fix-
Author | SHA1 | Date | |
---|---|---|---|
1953ca0607 | |||
cb9fa71645 | |||
a7f0a5607d | |||
eb28ed6cbf | |||
3c84ef8592 | |||
9b966de7f0 |
@ -84,7 +84,11 @@ import {
|
||||
createPipeSubstitution,
|
||||
findUniqueName,
|
||||
} from 'lang/modifyAst'
|
||||
import { Selections, getEventForSegmentSelection } from 'lib/selections'
|
||||
import {
|
||||
Selection,
|
||||
Selections,
|
||||
getEventForSegmentSelection,
|
||||
} from 'lib/selections'
|
||||
import { getTangentPointFromPreviousArc } from 'lib/utils2d'
|
||||
import { createGridHelper, orthoScale, perspScale } from './helpers'
|
||||
import { Models } from '@kittycad/lib'
|
||||
@ -98,6 +102,11 @@ import {
|
||||
import { getThemeColorForThreeJs } from 'lib/theme'
|
||||
import { err, trap } from 'lib/trap'
|
||||
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
|
||||
import {
|
||||
ArtifactGraph,
|
||||
ArtifactId,
|
||||
getPlaneOrFaceFromSelection,
|
||||
} from 'lang/std/artifactGraph'
|
||||
|
||||
type DraftSegment = 'line' | 'tangentialArcTo'
|
||||
|
||||
@ -582,15 +591,20 @@ export class SceneEntities {
|
||||
const _node1 = getNodeFromPath<VariableDeclaration>(
|
||||
_ast,
|
||||
sketchPathToNode || [],
|
||||
'VariableDeclaration'
|
||||
)
|
||||
['VariableDeclaration', 'ExpressionStatement']
|
||||
) as { node: { type: string } } | Error
|
||||
if (trap(_node1)) return Promise.reject(_node1)
|
||||
const variableDeclarationName =
|
||||
_node1.node?.declarations?.[0]?.id?.name || ''
|
||||
const variableDeclarationName = (_node1.node.type === 'VariableDeclaration') ?
|
||||
(_node1.node as VariableDeclaration).declarations[0]?.id?.name || '' :
|
||||
''
|
||||
|
||||
const sg = kclManager.programMemory.get(
|
||||
const sgMemItem = kclManager.programMemory.get(
|
||||
variableDeclarationName
|
||||
) as SketchGroup
|
||||
)
|
||||
if (sgMemItem?.type !== 'SketchGroup') {
|
||||
return Promise.reject(new Error('SketchGroup not found in programMemory'))
|
||||
}
|
||||
const sg: SketchGroup = sgMemItem
|
||||
const lastSeg = sg.value.slice(-1)[0] || sg.start
|
||||
|
||||
const index = sg.value.length // because we've added a new segment that's not in the memory yet, no need for `-1`
|
||||
@ -1762,6 +1776,33 @@ export function getParentGroup(
|
||||
return null
|
||||
}
|
||||
|
||||
export async function planeOrFaceFromSelection({
|
||||
artifactGraph,
|
||||
selection,
|
||||
}: {
|
||||
artifactGraph: ArtifactGraph
|
||||
selection: Selection
|
||||
}): Promise<{
|
||||
id: ArtifactId
|
||||
faceDetails: Models['GetSketchModePlane_type']
|
||||
} | null> {
|
||||
// If the selection doesn't have an artifactId associated with it, we can't
|
||||
// do it.
|
||||
if (!selection.artifactId) return null
|
||||
|
||||
const planeOrFace = getPlaneOrFaceFromSelection(
|
||||
selection.artifactId,
|
||||
artifactGraph
|
||||
)
|
||||
if (!planeOrFace) return null
|
||||
if (planeOrFace?.type === 'plane') {
|
||||
const faceDetails = await getFaceDetails(planeOrFace.id)
|
||||
return { id: planeOrFace.id, faceDetails }
|
||||
}
|
||||
// TODO: Handle wall or cap artifact.
|
||||
return null
|
||||
}
|
||||
|
||||
export function sketchGroupFromPathToNode({
|
||||
pathToNode,
|
||||
ast,
|
||||
@ -1827,11 +1868,51 @@ export function getSketchQuaternion(
|
||||
return getQuaternionFromZAxis(massageFormats(zAxis))
|
||||
}
|
||||
export async function getSketchOrientationDetails(
|
||||
artifactGraph: ArtifactGraph,
|
||||
selection: Selection,
|
||||
sketchPathToNode: PathToNode
|
||||
): Promise<{
|
||||
quat: Quaternion
|
||||
sketchDetails: SketchDetails & { faceId?: string }
|
||||
sketchDetails: {
|
||||
zAxis: [number, number, number]
|
||||
yAxis: [number, number, number]
|
||||
origin: [number, number, number]
|
||||
faceId: string
|
||||
}
|
||||
}> {
|
||||
const plane = await planeOrFaceFromSelection({
|
||||
artifactGraph,
|
||||
selection,
|
||||
})
|
||||
if (plane) {
|
||||
const details = plane.faceDetails
|
||||
console.warn('Found plane', plane)
|
||||
const zAxis: [number, number, number] = [
|
||||
details.z_axis.x,
|
||||
details.z_axis.y,
|
||||
details.z_axis.z,
|
||||
]
|
||||
const yAxis: [number, number, number] = [
|
||||
details.y_axis.x,
|
||||
details.y_axis.y,
|
||||
details.y_axis.z,
|
||||
]
|
||||
const origin: [number, number, number] = [
|
||||
details.origin.x,
|
||||
details.origin.y,
|
||||
details.origin.z,
|
||||
]
|
||||
return {
|
||||
sketchDetails: {
|
||||
zAxis,
|
||||
yAxis,
|
||||
origin,
|
||||
faceId: plane.id,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// We couldn't find the plane or face, so try to look at the AST, and find it
|
||||
// through there.
|
||||
const sketchGroup = sketchGroupFromPathToNode({
|
||||
pathToNode: sketchPathToNode,
|
||||
ast: kclManager.ast,
|
||||
@ -1843,9 +1924,7 @@ export async function getSketchOrientationDetails(
|
||||
if (sketchGroup.on.type === 'plane') {
|
||||
const zAxis = sketchGroup?.on.zAxis
|
||||
return {
|
||||
quat: getQuaternionFromZAxis(massageFormats(zAxis)),
|
||||
sketchDetails: {
|
||||
sketchPathToNode,
|
||||
zAxis: [zAxis.x, zAxis.y, zAxis.z],
|
||||
yAxis: [
|
||||
sketchGroup.on.yAxis.x,
|
||||
@ -1864,14 +1943,8 @@ export async function getSketchOrientationDetails(
|
||||
if (!faceInfo?.origin || !faceInfo?.z_axis || !faceInfo?.y_axis)
|
||||
return Promise.reject('face info')
|
||||
const { z_axis, y_axis, origin } = faceInfo
|
||||
const quaternion = quaternionFromUpNForward(
|
||||
new Vector3(y_axis.x, y_axis.y, y_axis.z),
|
||||
new Vector3(z_axis.x, z_axis.y, z_axis.z)
|
||||
)
|
||||
return {
|
||||
quat: quaternion,
|
||||
sketchDetails: {
|
||||
sketchPathToNode,
|
||||
zAxis: [z_axis.x, z_axis.y, z_axis.z],
|
||||
yAxis: [y_axis.x, y_axis.y, y_axis.z],
|
||||
origin: [origin.x, origin.y, origin.z],
|
||||
|
@ -589,12 +589,17 @@ export const ModelingMachineProvider = ({
|
||||
}
|
||||
},
|
||||
'animate-to-sketch': async ({ selectionRanges }) => {
|
||||
const sourceRange = selectionRanges.codeBasedSelections[0].range
|
||||
const selection = selectionRanges.codeBasedSelections[0]
|
||||
const sourceRange = selection.range
|
||||
const sketchPathToNode = getNodePathFromSourceRange(
|
||||
kclManager.ast,
|
||||
sourceRange
|
||||
)
|
||||
const info = await getSketchOrientationDetails(sketchPathToNode || [])
|
||||
const info = await getSketchOrientationDetails(
|
||||
engineCommandManager.artifactGraph,
|
||||
selection,
|
||||
sketchPathToNode || []
|
||||
)
|
||||
await letEngineAnimateAndSyncCamAfter(
|
||||
engineCommandManager,
|
||||
info?.sketchDetails?.faceId || ''
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
ProgramMemory,
|
||||
SourceRange,
|
||||
SketchGroup,
|
||||
ExpressionStatement,
|
||||
} from './wasm'
|
||||
import {
|
||||
isNodeSafeToReplacePath,
|
||||
@ -82,15 +83,22 @@ export function addStartProfileAt(
|
||||
const _node1 = getNodeFromPath<VariableDeclaration>(
|
||||
node,
|
||||
pathToNode,
|
||||
'VariableDeclaration'
|
||||
)
|
||||
['VariableDeclaration', 'ExpressionStatement']
|
||||
) as { node: { type: string } } | Error
|
||||
if (err(_node1)) return _node1
|
||||
const variableDeclaration = _node1.node
|
||||
if (variableDeclaration.type !== 'VariableDeclaration') {
|
||||
return new Error('variableDeclaration.init.type !== PipeExpression')
|
||||
}
|
||||
const _node = { ...node }
|
||||
const init = variableDeclaration.declarations[0].init
|
||||
let expr: Value
|
||||
let variableDeclaration: VariableDeclaration | undefined
|
||||
if (_node1.node.type === 'VariableDeclaration') {
|
||||
const node: VariableDeclaration = _node1.node as VariableDeclaration
|
||||
variableDeclaration = node
|
||||
expr = node.declarations[0].init
|
||||
} else if (_node1.node.type === 'ExpressionStatement') {
|
||||
const node: ExpressionStatement = _node1.node as ExpressionStatement
|
||||
expr = node.expression
|
||||
} else {
|
||||
return new Error(`Unrecognized node type ${_node1.node.type}`)
|
||||
}
|
||||
const startProfileAt = createCallExpressionStdLib('startProfileAt', [
|
||||
createArrayExpression([
|
||||
createLiteral(roundOff(at[0])),
|
||||
@ -98,11 +106,11 @@ export function addStartProfileAt(
|
||||
]),
|
||||
createPipeSubstitution(),
|
||||
])
|
||||
if (init.type === 'PipeExpression') {
|
||||
init.body.splice(1, 0, startProfileAt)
|
||||
} else {
|
||||
if (expr.type === 'PipeExpression') {
|
||||
expr.body.splice(1, 0, startProfileAt)
|
||||
} else if (variableDeclaration) {
|
||||
variableDeclaration.declarations[0].init = createPipeExpression([
|
||||
init,
|
||||
expr,
|
||||
startProfileAt,
|
||||
])
|
||||
}
|
||||
|
@ -791,7 +791,7 @@ export function isSingleCursorInPipe(
|
||||
const pathToNode = getNodePathFromSourceRange(ast, selection.range)
|
||||
const nodeTypes = pathToNode.map(([, type]) => type)
|
||||
if (nodeTypes.includes('FunctionExpression')) return false
|
||||
if (!nodeTypes.includes('VariableDeclaration')) return false
|
||||
// if (!nodeTypes.includes('VariableDeclaration')) return false
|
||||
if (nodeTypes.includes('PipeExpression')) return true
|
||||
return false
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ import { Models } from '@kittycad/lib'
|
||||
import { getNodePathFromSourceRange } from 'lang/queryAst'
|
||||
import { err } from 'lib/trap'
|
||||
|
||||
export type ArtifactId = string
|
||||
|
||||
interface CommonCommandProperties {
|
||||
range: SourceRange
|
||||
pathToNode: PathToNode
|
||||
@ -10,17 +12,20 @@ interface CommonCommandProperties {
|
||||
|
||||
export interface PlaneArtifact {
|
||||
type: 'plane'
|
||||
id: ArtifactId
|
||||
pathIds: Array<string>
|
||||
codeRef: CommonCommandProperties
|
||||
}
|
||||
export interface PlaneArtifactRich {
|
||||
type: 'plane'
|
||||
id: ArtifactId
|
||||
paths: Array<PathArtifact>
|
||||
codeRef: CommonCommandProperties
|
||||
}
|
||||
|
||||
export interface PathArtifact {
|
||||
type: 'path'
|
||||
id: ArtifactId
|
||||
planeId: string
|
||||
segIds: Array<string>
|
||||
extrusionId: string
|
||||
@ -30,10 +35,12 @@ export interface PathArtifact {
|
||||
|
||||
interface solid2D {
|
||||
type: 'solid2D'
|
||||
id: ArtifactId
|
||||
pathId: string
|
||||
}
|
||||
export interface PathArtifactRich {
|
||||
type: 'path'
|
||||
id: ArtifactId
|
||||
plane: PlaneArtifact | WallArtifact
|
||||
segments: Array<SegmentArtifact>
|
||||
extrusion: ExtrusionArtifact
|
||||
@ -42,6 +49,7 @@ export interface PathArtifactRich {
|
||||
|
||||
interface SegmentArtifact {
|
||||
type: 'segment'
|
||||
id: ArtifactId
|
||||
pathId: string
|
||||
surfaceId: string
|
||||
edgeIds: Array<string>
|
||||
@ -50,6 +58,7 @@ interface SegmentArtifact {
|
||||
}
|
||||
interface SegmentArtifactRich {
|
||||
type: 'segment'
|
||||
id: ArtifactId
|
||||
path: PathArtifact
|
||||
surf: WallArtifact
|
||||
edges: Array<ExtrudeEdge>
|
||||
@ -59,6 +68,7 @@ interface SegmentArtifactRich {
|
||||
|
||||
interface ExtrusionArtifact {
|
||||
type: 'extrusion'
|
||||
id: ArtifactId
|
||||
pathId: string
|
||||
surfaceIds: Array<string>
|
||||
edgeIds: Array<string>
|
||||
@ -66,6 +76,7 @@ interface ExtrusionArtifact {
|
||||
}
|
||||
interface ExtrusionArtifactRich {
|
||||
type: 'extrusion'
|
||||
id: ArtifactId
|
||||
path: PathArtifact
|
||||
surfaces: Array<WallArtifact | CapArtifact>
|
||||
edges: Array<ExtrudeEdge>
|
||||
@ -74,6 +85,7 @@ interface ExtrusionArtifactRich {
|
||||
|
||||
interface WallArtifact {
|
||||
type: 'wall'
|
||||
id: ArtifactId
|
||||
segId: string
|
||||
edgeCutEdgeIds: Array<string>
|
||||
extrusionId: string
|
||||
@ -81,6 +93,7 @@ interface WallArtifact {
|
||||
}
|
||||
interface CapArtifact {
|
||||
type: 'cap'
|
||||
id: ArtifactId
|
||||
subType: 'start' | 'end'
|
||||
edgeCutEdgeIds: Array<string>
|
||||
extrusionId: string
|
||||
@ -89,6 +102,7 @@ interface CapArtifact {
|
||||
|
||||
interface ExtrudeEdge {
|
||||
type: 'extrudeEdge'
|
||||
id: ArtifactId
|
||||
segId: string
|
||||
extrusionId: string
|
||||
edgeId: string
|
||||
@ -97,6 +111,7 @@ interface ExtrudeEdge {
|
||||
/** A edgeCut is a more generic term for both fillet or chamfer */
|
||||
interface EdgeCut {
|
||||
type: 'edgeCut'
|
||||
id: ArtifactId
|
||||
subType: 'fillet' | 'chamfer'
|
||||
consumedEdgeId: string
|
||||
edgeIds: Array<string>
|
||||
@ -106,6 +121,7 @@ interface EdgeCut {
|
||||
|
||||
interface EdgeCutEdge {
|
||||
type: 'edgeCutEdge'
|
||||
id: ArtifactId
|
||||
edgeCutId: string
|
||||
surfaceId: string
|
||||
}
|
||||
@ -122,7 +138,7 @@ export type Artifact =
|
||||
| EdgeCutEdge
|
||||
| solid2D
|
||||
|
||||
export type ArtifactGraph = Map<string, Artifact>
|
||||
export type ArtifactGraph = Map<ArtifactId, Artifact>
|
||||
|
||||
export type EngineCommand = Models['WebSocketRequest_type']
|
||||
|
||||
@ -149,7 +165,7 @@ export function createArtifactGraph({
|
||||
responseMap: ResponseMap
|
||||
ast: Program
|
||||
}) {
|
||||
const myMap = new Map<string, Artifact>()
|
||||
const myMap = new Map<ArtifactId, Artifact>()
|
||||
|
||||
/** see docstring for {@link getArtifactsToUpdate} as to why this is needed */
|
||||
let currentPlaneId = ''
|
||||
@ -166,7 +182,7 @@ export function createArtifactGraph({
|
||||
const artifactsToUpdate = getArtifactsToUpdate({
|
||||
orderedCommand,
|
||||
responseMap,
|
||||
getArtifact: (id: string) => myMap.get(id),
|
||||
getArtifact: (id: ArtifactId) => myMap.get(id),
|
||||
currentPlaneId,
|
||||
ast,
|
||||
})
|
||||
@ -210,7 +226,7 @@ function mergeArtifacts(
|
||||
* It does not mutate the map directly, but returns an array of artifacts to update
|
||||
*
|
||||
* @param currentPlaneId is only needed for `start_path` commands because this command does not have a pathId
|
||||
* instead it relies on the id used with the `enable_sketch_mode` command, so this much be kept track of
|
||||
* instead it relies on the id used with the `enable_sketch_mode` command, so this must be kept track of
|
||||
* outside of this function. It would be good to update the `start_path` command to include the planeId so we
|
||||
* can remove this.
|
||||
*/
|
||||
@ -224,11 +240,11 @@ export function getArtifactsToUpdate({
|
||||
orderedCommand: OrderedCommand
|
||||
responseMap: ResponseMap
|
||||
/** Passing in a getter because we don't wan this function to update the map directly */
|
||||
getArtifact: (id: string) => Artifact | undefined
|
||||
getArtifact: (id: ArtifactId) => Artifact | undefined
|
||||
currentPlaneId: string
|
||||
ast: Program
|
||||
}): Array<{
|
||||
id: string
|
||||
id: ArtifactId
|
||||
artifact: Artifact
|
||||
}> {
|
||||
const pathToNode = getNodePathFromSourceRange(ast, range)
|
||||
@ -253,6 +269,7 @@ export function getArtifactsToUpdate({
|
||||
id: currentPlaneId,
|
||||
artifact: {
|
||||
type: 'wall',
|
||||
id: currentPlaneId,
|
||||
segId: existingPlane.segId,
|
||||
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
|
||||
extrusionId: existingPlane.extrusionId,
|
||||
@ -262,7 +279,10 @@ export function getArtifactsToUpdate({
|
||||
]
|
||||
} else {
|
||||
return [
|
||||
{ id: currentPlaneId, artifact: { type: 'plane', pathIds, codeRef } },
|
||||
{
|
||||
id: currentPlaneId,
|
||||
artifact: { type: 'plane', id: currentPlaneId, pathIds, codeRef },
|
||||
},
|
||||
]
|
||||
}
|
||||
} else if (cmd.type === 'start_path') {
|
||||
@ -270,6 +290,7 @@ export function getArtifactsToUpdate({
|
||||
id,
|
||||
artifact: {
|
||||
type: 'path',
|
||||
id,
|
||||
segIds: [],
|
||||
planeId: currentPlaneId,
|
||||
extrusionId: '',
|
||||
@ -282,7 +303,7 @@ export function getArtifactsToUpdate({
|
||||
if (plane?.type === 'plane') {
|
||||
returnArr.push({
|
||||
id: currentPlaneId,
|
||||
artifact: { type: 'plane', pathIds: [id], codeRef },
|
||||
artifact: { type: 'plane', id: currentPlaneId, pathIds: [id], codeRef },
|
||||
})
|
||||
}
|
||||
if (plane?.type === 'wall') {
|
||||
@ -290,6 +311,7 @@ export function getArtifactsToUpdate({
|
||||
id: currentPlaneId,
|
||||
artifact: {
|
||||
type: 'wall',
|
||||
id: currentPlaneId,
|
||||
segId: plane.segId,
|
||||
edgeCutEdgeIds: plane.edgeCutEdgeIds,
|
||||
extrusionId: plane.extrusionId,
|
||||
@ -304,6 +326,7 @@ export function getArtifactsToUpdate({
|
||||
id,
|
||||
artifact: {
|
||||
type: 'segment',
|
||||
id,
|
||||
pathId,
|
||||
surfaceId: '',
|
||||
edgeIds: [],
|
||||
@ -313,21 +336,22 @@ export function getArtifactsToUpdate({
|
||||
const path = getArtifact(pathId)
|
||||
if (path?.type === 'path')
|
||||
returnArr.push({
|
||||
id: pathId,
|
||||
id: path.id,
|
||||
artifact: { ...path, segIds: [id] },
|
||||
})
|
||||
if (
|
||||
response?.type === 'modeling' &&
|
||||
response.data.modeling_response.type === 'close_path'
|
||||
) {
|
||||
const id = response.data.modeling_response.data.face_id
|
||||
returnArr.push({
|
||||
id: response.data.modeling_response.data.face_id,
|
||||
artifact: { type: 'solid2D', pathId },
|
||||
id,
|
||||
artifact: { type: 'solid2D', id, pathId },
|
||||
})
|
||||
const path = getArtifact(pathId)
|
||||
if (path?.type === 'path')
|
||||
returnArr.push({
|
||||
id: pathId,
|
||||
id: path.id,
|
||||
artifact: {
|
||||
...path,
|
||||
solid2dId: response.data.modeling_response.data.face_id,
|
||||
@ -340,6 +364,7 @@ export function getArtifactsToUpdate({
|
||||
id,
|
||||
artifact: {
|
||||
type: 'extrusion',
|
||||
id,
|
||||
pathId: cmd.target,
|
||||
surfaceIds: [],
|
||||
edgeIds: [],
|
||||
@ -349,7 +374,7 @@ export function getArtifactsToUpdate({
|
||||
const path = getArtifact(cmd.target)
|
||||
if (path?.type === 'path')
|
||||
returnArr.push({
|
||||
id: cmd.target,
|
||||
id: path.id,
|
||||
artifact: { ...path, extrusionId: id },
|
||||
})
|
||||
return returnArr
|
||||
@ -371,6 +396,7 @@ export function getArtifactsToUpdate({
|
||||
id: face_id,
|
||||
artifact: {
|
||||
type: 'wall',
|
||||
id: face_id,
|
||||
segId: curve_id,
|
||||
edgeCutEdgeIds: [],
|
||||
extrusionId: path.extrusionId,
|
||||
@ -378,7 +404,7 @@ export function getArtifactsToUpdate({
|
||||
},
|
||||
})
|
||||
returnArr.push({
|
||||
id: curve_id,
|
||||
id: seg.id,
|
||||
artifact: { ...seg, surfaceId: face_id },
|
||||
})
|
||||
const extrusion = getArtifact(path.extrusionId)
|
||||
@ -403,6 +429,7 @@ export function getArtifactsToUpdate({
|
||||
id: face_id,
|
||||
artifact: {
|
||||
type: 'cap',
|
||||
id: face_id,
|
||||
subType: cap === 'bottom' ? 'start' : 'end',
|
||||
edgeCutEdgeIds: [],
|
||||
extrusionId: path.extrusionId,
|
||||
@ -412,7 +439,7 @@ export function getArtifactsToUpdate({
|
||||
const extrusion = getArtifact(path.extrusionId)
|
||||
if (extrusion?.type !== 'extrusion') return
|
||||
returnArr.push({
|
||||
id: path.extrusionId,
|
||||
id: extrusion.id,
|
||||
artifact: {
|
||||
...extrusion,
|
||||
surfaceIds: [face_id],
|
||||
@ -427,6 +454,7 @@ export function getArtifactsToUpdate({
|
||||
id,
|
||||
artifact: {
|
||||
type: 'edgeCut',
|
||||
id,
|
||||
subType: cmd.cut_type,
|
||||
consumedEdgeId: cmd.edge_id,
|
||||
edgeIds: [],
|
||||
@ -437,7 +465,7 @@ export function getArtifactsToUpdate({
|
||||
const consumedEdge = getArtifact(cmd.edge_id)
|
||||
if (consumedEdge?.type === 'segment') {
|
||||
returnArr.push({
|
||||
id: cmd.edge_id,
|
||||
id: consumedEdge.id,
|
||||
artifact: { ...consumedEdge, edgeCutId: id },
|
||||
})
|
||||
}
|
||||
@ -464,7 +492,7 @@ export function filterArtifacts<T extends Artifact['type'][]>(
|
||||
(!predicate ||
|
||||
predicate(value as Extract<Artifact, { type: T[number] }>))
|
||||
)
|
||||
) as Map<string, Extract<Artifact, { type: T[number] }>>
|
||||
) as Map<ArtifactId, Extract<Artifact, { type: T[number] }>>
|
||||
}
|
||||
|
||||
export function getArtifactsOfTypes<T extends Artifact['type'][]>(
|
||||
@ -478,7 +506,7 @@ export function getArtifactsOfTypes<T extends Artifact['type'][]>(
|
||||
predicate?: (value: Extract<Artifact, { type: T[number] }>) => boolean
|
||||
},
|
||||
map: ArtifactGraph
|
||||
): Map<string, Extract<Artifact, { type: T[number] }>> {
|
||||
): Map<ArtifactId, Extract<Artifact, { type: T[number] }>> {
|
||||
return new Map(
|
||||
[...map].filter(
|
||||
([key, value]) =>
|
||||
@ -487,7 +515,7 @@ export function getArtifactsOfTypes<T extends Artifact['type'][]>(
|
||||
(!predicate ||
|
||||
predicate(value as Extract<Artifact, { type: T[number] }>))
|
||||
)
|
||||
) as Map<string, Extract<Artifact, { type: T[number] }>>
|
||||
) as Map<ArtifactId, Extract<Artifact, { type: T[number] }>>
|
||||
}
|
||||
|
||||
export function getArtifactOfTypes<T extends Artifact['type'][]>(
|
||||
@ -495,7 +523,7 @@ export function getArtifactOfTypes<T extends Artifact['type'][]>(
|
||||
key,
|
||||
types,
|
||||
}: {
|
||||
key: string
|
||||
key: ArtifactId
|
||||
types: T
|
||||
},
|
||||
map: ArtifactGraph
|
||||
@ -517,6 +545,7 @@ export function expandPlane(
|
||||
)
|
||||
return {
|
||||
type: 'plane',
|
||||
id: plane.id,
|
||||
paths: Array.from(paths.values()),
|
||||
codeRef: plane.codeRef,
|
||||
}
|
||||
@ -545,6 +574,7 @@ export function expandPath(
|
||||
if (err(plane)) return plane
|
||||
return {
|
||||
type: 'path',
|
||||
id: path.id,
|
||||
segments: Array.from(segs.values()),
|
||||
extrusion,
|
||||
plane,
|
||||
@ -571,6 +601,7 @@ export function expandExtrusion(
|
||||
if (err(path)) return path
|
||||
return {
|
||||
type: 'extrusion',
|
||||
id: extrusion.id,
|
||||
surfaces: Array.from(surfs.values()),
|
||||
edges: Array.from(edges.values()),
|
||||
path,
|
||||
@ -606,6 +637,7 @@ export function expandSegment(
|
||||
|
||||
return {
|
||||
type: 'segment',
|
||||
id: segment.id,
|
||||
path,
|
||||
surf,
|
||||
edges: Array.from(edges.values()),
|
||||
@ -656,7 +688,7 @@ export function getWallCodeRef(
|
||||
}
|
||||
|
||||
export function getExtrusionFromSuspectedExtrudeSurface(
|
||||
id: string,
|
||||
id: ArtifactId,
|
||||
artifactGraph: ArtifactGraph
|
||||
): ExtrusionArtifact | Error {
|
||||
const artifact = getArtifactOfTypes(
|
||||
@ -671,7 +703,7 @@ export function getExtrusionFromSuspectedExtrudeSurface(
|
||||
}
|
||||
|
||||
export function getExtrusionFromSuspectedPath(
|
||||
id: string,
|
||||
id: ArtifactId,
|
||||
artifactGraph: ArtifactGraph
|
||||
): ExtrusionArtifact | Error {
|
||||
const path = getArtifactOfTypes({ key: id, types: ['path'] }, artifactGraph)
|
||||
@ -681,3 +713,33 @@ export function getExtrusionFromSuspectedPath(
|
||||
artifactGraph
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plane or face from a selection.
|
||||
*
|
||||
* TODO: Handle sketch on face.
|
||||
*/
|
||||
export function getPlaneOrFaceFromSelection(
|
||||
id: ArtifactId,
|
||||
artifactGraph: ArtifactGraph
|
||||
): PlaneArtifactRich | null {
|
||||
const selection = artifactGraph.get(id)
|
||||
if (!selection) return null
|
||||
if (selection.type === 'solid2D') {
|
||||
const path = artifactGraph.get(selection.pathId)
|
||||
if (path?.type !== 'path') return null
|
||||
const plane = artifactGraph.get(path.planeId)
|
||||
if (plane?.type !== 'plane') return null
|
||||
return expandPlane(plane, artifactGraph)
|
||||
} else if (selection.type === 'wall' || selection.type === 'cap') {
|
||||
const extrusion = artifactGraph.get(selection.extrusionId)
|
||||
if (extrusion?.type !== 'extrusion') return null
|
||||
const path = artifactGraph.get(extrusion.pathId)
|
||||
if (path?.type !== 'path') return null
|
||||
const plane = artifactGraph.get(path.planeId)
|
||||
// TODO: For sketch on face, this won't be a plane.
|
||||
if (plane?.type !== 'plane') return null
|
||||
return expandPlane(plane, artifactGraph)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import { AXIS_GROUP, X_AXIS } from 'clientSideScene/sceneInfra'
|
||||
import { PathToNodeMap } from 'lang/std/sketchcombos'
|
||||
import { err } from 'lib/trap'
|
||||
import {
|
||||
ArtifactId,
|
||||
getArtifactOfTypes,
|
||||
getArtifactsOfTypes,
|
||||
getCapCodeRef,
|
||||
@ -56,6 +57,7 @@ export type Selection = {
|
||||
| 'line'
|
||||
| 'arc'
|
||||
| 'all'
|
||||
artifactId?: ArtifactId
|
||||
range: SourceRange
|
||||
}
|
||||
export type Selections = {
|
||||
@ -100,7 +102,11 @@ export async function getEventForSelectWithPoint({
|
||||
type: 'Set selection',
|
||||
data: {
|
||||
selectionType: 'singleCodeCursor',
|
||||
selection: { range: codeRef.range, type: 'solid2D' },
|
||||
selection: {
|
||||
artifactId: data.entity_id,
|
||||
range: codeRef.range,
|
||||
type: 'solid2D',
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -112,6 +118,7 @@ export async function getEventForSelectWithPoint({
|
||||
data: {
|
||||
selectionType: 'singleCodeCursor',
|
||||
selection: {
|
||||
artifactId: data.entity_id,
|
||||
range: codeRef.range,
|
||||
type: _artifact?.subType === 'end' ? 'end-cap' : 'start-cap',
|
||||
},
|
||||
@ -128,7 +135,11 @@ export async function getEventForSelectWithPoint({
|
||||
type: 'Set selection',
|
||||
data: {
|
||||
selectionType: 'singleCodeCursor',
|
||||
selection: { range: codeRef.range, type: 'extrude-wall' },
|
||||
selection: {
|
||||
artifactId: data.entity_id,
|
||||
range: codeRef.range,
|
||||
type: 'extrude-wall',
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -137,7 +148,11 @@ export async function getEventForSelectWithPoint({
|
||||
type: 'Set selection',
|
||||
data: {
|
||||
selectionType: 'singleCodeCursor',
|
||||
selection: { range: _artifact.codeRef.range, type: 'default' },
|
||||
selection: {
|
||||
artifactId: data.entity_id,
|
||||
range: _artifact.codeRef.range,
|
||||
type: 'default',
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -642,9 +657,12 @@ export function updateSelections(
|
||||
const nodeMeta = getNodeFromPath<Value>(ast, pathToNode)
|
||||
if (err(nodeMeta)) return undefined
|
||||
const node = nodeMeta.node
|
||||
const prevCodeBasedSelection =
|
||||
prevSelectionRanges.codeBasedSelections[Number(index)]
|
||||
return {
|
||||
artifactId: prevCodeBasedSelection?.artifactId,
|
||||
range: [node.start, node.end],
|
||||
type: prevSelectionRanges.codeBasedSelections[Number(index)]?.type,
|
||||
type: prevCodeBasedSelection?.type,
|
||||
}
|
||||
})
|
||||
.filter((x?: Selection) => x !== undefined) as Selection[]
|
||||
|
Reference in New Issue
Block a user