Compare commits
4 Commits
jtran/plus
...
safe-reset
Author | SHA1 | Date | |
---|---|---|---|
10c51896be | |||
34f05b3cf2 | |||
3c89ac8421 | |||
d3f788050c |
@ -81,9 +81,7 @@ function CommandBarSelectionInput({
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
toSync(() => {
|
toSync(() => {
|
||||||
const promises = [
|
const promises = [kclManager.defaultSelectionFilter(selection)]
|
||||||
new Promise(() => kclManager.defaultSelectionFilter(selection)),
|
|
||||||
]
|
|
||||||
if (!kclManager._isAstEmpty(kclManager.ast)) {
|
if (!kclManager._isAstEmpty(kclManager.ast)) {
|
||||||
promises.push(kclManager.hidePlanes())
|
promises.push(kclManager.hidePlanes())
|
||||||
}
|
}
|
||||||
@ -130,7 +128,10 @@ function CommandBarSelectionInput({
|
|||||||
// Set selection filter if needed, and reset it when the component unmounts
|
// Set selection filter if needed, and reset it when the component unmounts
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
arg.selectionFilter && kclManager.setSelectionFilter(arg.selectionFilter)
|
arg.selectionFilter && kclManager.setSelectionFilter(arg.selectionFilter)
|
||||||
return () => kclManager.defaultSelectionFilter(selection)
|
// TODO: We shouldn't use async here.
|
||||||
|
return toSync(async () => {
|
||||||
|
await kclManager.defaultSelectionFilter(selection)
|
||||||
|
}, reportRejection)
|
||||||
}, [arg.selectionFilter])
|
}, [arg.selectionFilter])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -8,6 +8,8 @@ import {
|
|||||||
getSelectionCountByType,
|
getSelectionCountByType,
|
||||||
} from '@src/lib/selections'
|
} from '@src/lib/selections'
|
||||||
import { kclManager } from '@src/lib/singletons'
|
import { kclManager } from '@src/lib/singletons'
|
||||||
|
import { reportRejection } from '@src/lib/trap'
|
||||||
|
import { toSync } from '@src/lib/utils'
|
||||||
import {
|
import {
|
||||||
commandBarActor,
|
commandBarActor,
|
||||||
useCommandBarState,
|
useCommandBarState,
|
||||||
@ -64,7 +66,10 @@ export default function CommandBarSelectionMixedInput({
|
|||||||
// Set selection filter if needed, and reset it when the component unmounts
|
// Set selection filter if needed, and reset it when the component unmounts
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
arg.selectionFilter && kclManager.setSelectionFilter(arg.selectionFilter)
|
arg.selectionFilter && kclManager.setSelectionFilter(arg.selectionFilter)
|
||||||
return () => kclManager.defaultSelectionFilter(selection)
|
// TODO: We shouldn't use async here.
|
||||||
|
return toSync(async () => {
|
||||||
|
await kclManager.defaultSelectionFilter(selection)
|
||||||
|
}, reportRejection)
|
||||||
}, [arg.selectionFilter])
|
}, [arg.selectionFilter])
|
||||||
|
|
||||||
function handleChange() {
|
function handleChange() {
|
||||||
|
@ -211,6 +211,22 @@ export const ModelingMachineProvider = ({
|
|||||||
.catch(reportRejection)
|
.catch(reportRejection)
|
||||||
})().catch(reportRejection)
|
})().catch(reportRejection)
|
||||||
},
|
},
|
||||||
|
execute: ({ context: { store } }) => {
|
||||||
|
// TODO: Remove this async callback. For some reason eslint wouldn't
|
||||||
|
// let me disable @typescript-eslint/no-misused-promises for the line.
|
||||||
|
;(async () => {
|
||||||
|
return kclManager
|
||||||
|
.executeCode()
|
||||||
|
.then(() => {
|
||||||
|
if (engineCommandManager.engineConnection?.idleMode) return
|
||||||
|
|
||||||
|
store.videoElement?.play().catch((e) => {
|
||||||
|
console.warn('Video playing was prevented', e)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(reportRejection)
|
||||||
|
})().catch(reportRejection)
|
||||||
|
},
|
||||||
'Set mouse state': assign(({ context, event }) => {
|
'Set mouse state': assign(({ context, event }) => {
|
||||||
if (event.type !== 'Set mouse state') return {}
|
if (event.type !== 'Set mouse state') return {}
|
||||||
const nextSegmentHoverMap = () => {
|
const nextSegmentHoverMap = () => {
|
||||||
|
@ -268,13 +268,14 @@ export const Stream = () => {
|
|||||||
if (state.matches('Sketch')) return
|
if (state.matches('Sketch')) return
|
||||||
// Only respect default plane selection if we're on a selection command argument
|
// Only respect default plane selection if we're on a selection command argument
|
||||||
if (
|
if (
|
||||||
state.matches({ idle: 'showPlanes' }) &&
|
!kclManager.defaultPlanesShown &&
|
||||||
!(
|
!(
|
||||||
commandBarState.matches('Gathering arguments') &&
|
commandBarState.matches('Gathering arguments') &&
|
||||||
commandBarState.context.currentArgument?.inputType === 'selection'
|
commandBarState.context.currentArgument?.inputType === 'selection'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
// If we're mousing up from a camera drag, don't send a select event
|
// If we're mousing up from a camera drag, don't send a select event
|
||||||
if (sceneInfra.camControls.wasDragging === true) return
|
if (sceneInfra.camControls.wasDragging === true) return
|
||||||
|
|
||||||
@ -295,7 +296,7 @@ export const Stream = () => {
|
|||||||
!isNetworkOkay ||
|
!isNetworkOkay ||
|
||||||
!videoRef.current ||
|
!videoRef.current ||
|
||||||
state.matches('Sketch') ||
|
state.matches('Sketch') ||
|
||||||
state.matches({ idle: 'showPlanes' }) ||
|
!kclManager.defaultPlanesShown ||
|
||||||
sceneInfra.camControls.wasDragging === true ||
|
sceneInfra.camControls.wasDragging === true ||
|
||||||
!btnName(e.nativeEvent).left
|
!btnName(e.nativeEvent).left
|
||||||
) {
|
) {
|
||||||
|
@ -53,7 +53,7 @@ import {
|
|||||||
sceneInfra,
|
sceneInfra,
|
||||||
} from '@src/lib/singletons'
|
} from '@src/lib/singletons'
|
||||||
import { err, reportRejection } from '@src/lib/trap'
|
import { err, reportRejection } from '@src/lib/trap'
|
||||||
import { deferExecution, isOverlap, uuidv4 } from '@src/lib/utils'
|
import { isOverlap, uuidv4 } from '@src/lib/utils'
|
||||||
|
|
||||||
interface ExecuteArgs {
|
interface ExecuteArgs {
|
||||||
ast?: Node<Program>
|
ast?: Node<Program>
|
||||||
@ -317,23 +317,44 @@ export class KclManager {
|
|||||||
this.artifactGraph = execStateArtifactGraph
|
this.artifactGraph = execStateArtifactGraph
|
||||||
this.artifactIndex = buildArtifactIndex(execStateArtifactGraph)
|
this.artifactIndex = buildArtifactIndex(execStateArtifactGraph)
|
||||||
if (this.artifactGraph.size) {
|
if (this.artifactGraph.size) {
|
||||||
// TODO: we wanna remove this logic from xstate, it is racey
|
// Hide the planes.
|
||||||
// This defer is bullshit but playwright wants it
|
await Promise.all([this.hidePlanes(), this.defaultSelectionFilter()])
|
||||||
// It was like this in engineConnection.ts already
|
} else if (!this.hasErrors()) {
|
||||||
deferExecution((a?: null) => {
|
// Only show the planes if there are no errors.
|
||||||
this.engineCommandManager.modelingSend({
|
// Show the planes and reset.
|
||||||
type: 'Artifact graph emptied',
|
await this.showAndResetPlanes()
|
||||||
})
|
|
||||||
}, 200)(null)
|
|
||||||
} else {
|
|
||||||
deferExecution((a?: null) => {
|
|
||||||
this.engineCommandManager.modelingSend({
|
|
||||||
type: 'Artifact graph populated',
|
|
||||||
})
|
|
||||||
}, 200)(null)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async showAndResetPlanes(): Promise<void> {
|
||||||
|
await Promise.all([
|
||||||
|
this.showPlanes(),
|
||||||
|
this.resetCameraPosition(),
|
||||||
|
this.engineCommandManager.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'set_selection_filter',
|
||||||
|
filter: ['curve'],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
async resetCameraPosition(): Promise<void> {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
await this.engineCommandManager.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'default_camera_look_at',
|
||||||
|
center: { x: 0, y: 0, z: 0 },
|
||||||
|
vantage: { x: 0, y: -1250, z: 580 },
|
||||||
|
up: { x: 0, y: 0, z: 1 },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Some "objects" have the same source range, such as sketch_mode_start and start_path.
|
// Some "objects" have the same source range, such as sketch_mode_start and start_path.
|
||||||
// So when passing a range, we need to also specify the command type
|
// So when passing a range, we need to also specify the command type
|
||||||
private mapRangeToObjectId(
|
private mapRangeToObjectId(
|
||||||
@ -704,8 +725,9 @@ export class KclManager {
|
|||||||
return rustContext.defaultPlanes
|
return rustContext.defaultPlanes
|
||||||
}
|
}
|
||||||
|
|
||||||
showPlanes(all = false) {
|
async showPlanes(all = false): Promise<void> {
|
||||||
if (!this.defaultPlanes) return Promise.all([])
|
if (!this.defaultPlanes) return
|
||||||
|
this.defaultPlanesShown = true
|
||||||
const thePromises = [
|
const thePromises = [
|
||||||
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xy, false),
|
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xy, false),
|
||||||
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.yz, false),
|
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.yz, false),
|
||||||
@ -731,11 +753,12 @@ export class KclManager {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return Promise.all(thePromises)
|
await Promise.all(thePromises)
|
||||||
}
|
}
|
||||||
|
|
||||||
hidePlanes(all = false) {
|
async hidePlanes(all = false): Promise<void> {
|
||||||
if (!this.defaultPlanes) return Promise.all([])
|
if (!this.defaultPlanes) return
|
||||||
|
this.defaultPlanesShown = false
|
||||||
const thePromises = [
|
const thePromises = [
|
||||||
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xy, true),
|
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xy, true),
|
||||||
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.yz, true),
|
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.yz, true),
|
||||||
@ -752,15 +775,20 @@ export class KclManager {
|
|||||||
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.negXz, true)
|
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.negXz, true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return Promise.all(thePromises)
|
await Promise.all(thePromises)
|
||||||
}
|
}
|
||||||
/** TODO: this function is hiding unawaited asynchronous work */
|
|
||||||
defaultSelectionFilter(selectionsToRestore?: Selections) {
|
async defaultSelectionFilter(
|
||||||
setSelectionFilterToDefault(this.engineCommandManager, selectionsToRestore)
|
selectionsToRestore?: Selections
|
||||||
|
): Promise<void> {
|
||||||
|
await setSelectionFilterToDefault(
|
||||||
|
this.engineCommandManager,
|
||||||
|
selectionsToRestore
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/** TODO: this function is hiding unawaited asynchronous work */
|
|
||||||
setSelectionFilter(filter: EntityType_type[]) {
|
async setSelectionFilter(filter: EntityType_type[]): Promise<void> {
|
||||||
setSelectionFilter(filter, this.engineCommandManager)
|
await setSelectionFilter(filter, this.engineCommandManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -801,33 +829,29 @@ const defaultSelectionFilter: EntityType_type[] = [
|
|||||||
'object',
|
'object',
|
||||||
]
|
]
|
||||||
|
|
||||||
/** TODO: This function is not synchronous but is currently treated as such */
|
async function setSelectionFilterToDefault(
|
||||||
function setSelectionFilterToDefault(
|
|
||||||
engineCommandManager: EngineCommandManager,
|
engineCommandManager: EngineCommandManager,
|
||||||
selectionsToRestore?: Selections
|
selectionsToRestore?: Selections
|
||||||
) {
|
): Promise<void> {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
await setSelectionFilter(
|
||||||
setSelectionFilter(
|
|
||||||
defaultSelectionFilter,
|
defaultSelectionFilter,
|
||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
selectionsToRestore
|
selectionsToRestore
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** TODO: This function is not synchronous but is currently treated as such */
|
async function setSelectionFilter(
|
||||||
function setSelectionFilter(
|
|
||||||
filter: EntityType_type[],
|
filter: EntityType_type[],
|
||||||
engineCommandManager: EngineCommandManager,
|
engineCommandManager: EngineCommandManager,
|
||||||
selectionsToRestore?: Selections
|
selectionsToRestore?: Selections
|
||||||
) {
|
): Promise<void> {
|
||||||
const { engineEvents } = selectionsToRestore
|
const { engineEvents } = selectionsToRestore
|
||||||
? handleSelectionBatch({
|
? handleSelectionBatch({
|
||||||
selections: selectionsToRestore,
|
selections: selectionsToRestore,
|
||||||
})
|
})
|
||||||
: { engineEvents: undefined }
|
: { engineEvents: undefined }
|
||||||
if (!selectionsToRestore || !engineEvents) {
|
if (!selectionsToRestore || !engineEvents) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
await engineCommandManager.sendSceneCommand({
|
||||||
engineCommandManager.sendSceneCommand({
|
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
cmd: {
|
cmd: {
|
||||||
@ -847,7 +871,7 @@ function setSelectionFilter(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
// batch is needed other wise the selection flickers.
|
// batch is needed other wise the selection flickers.
|
||||||
engineCommandManager
|
await engineCommandManager
|
||||||
.sendSceneCommand({
|
.sendSceneCommand({
|
||||||
type: 'modeling_cmd_batch_req',
|
type: 'modeling_cmd_batch_req',
|
||||||
batch_id: uuidv4(),
|
batch_id: uuidv4(),
|
||||||
|
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user