2023-10-11 13:36:54 +11:00
import { PathToNode } from 'lang/wasm'
import { engineCommandManager } from 'lang/std/engineConnection'
import { isReducedMotion } from 'lang/util'
2023-10-16 21:20:05 +11:00
import {
Axis ,
Selection ,
SelectionRangeTypeMap ,
Selections ,
} from 'lib/selections'
2023-10-11 13:36:54 +11:00
import { assign , createMachine } from 'xstate'
import { v4 as uuidv4 } from 'uuid'
2023-10-11 15:12:29 +11:00
import { isCursorInSketchCommandRange } from 'lang/util'
2023-10-11 13:36:54 +11:00
import {
doesPipeHaveCallExp ,
getNodePathFromSourceRange ,
hasExtrudeSketchGroup ,
} from 'lang/queryAst'
import { kclManager } from 'lang/KclSinglton'
import {
horzVertInfo ,
applyConstraintHorzVert ,
} from 'components/Toolbar/HorzVert'
import {
applyConstraintHorzVertAlign ,
horzVertDistanceInfo ,
} from 'components/Toolbar/SetHorzVertDistance'
import { angleBetweenInfo } from 'components/Toolbar/SetAngleBetween'
import { setAngleLengthInfo } from 'components/Toolbar/setAngleLength'
import {
applyConstraintEqualLength ,
setEqualLengthInfo ,
} from 'components/Toolbar/EqualLength'
import { extrudeSketch } from 'lang/modifyAst'
import { getNodeFromPath } from '../lang/queryAst'
import { CallExpression , PipeExpression } from '../lang/wasm'
2023-10-14 03:47:46 +11:00
import { getConstraintLevelFromSourceRange } from 'lang/std/sketchcombos'
2023-10-16 08:54:38 +11:00
import {
applyConstraintEqualAngle ,
equalAngleInfo ,
} from 'components/Toolbar/EqualAngle'
import {
applyRemoveConstrainingValues ,
removeConstrainingValuesInfo ,
} from 'components/Toolbar/RemoveConstrainingValues'
import { intersectInfo } from 'components/Toolbar/Intersect'
2023-10-11 13:36:54 +11:00
export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'
export type SetSelections =
| {
selectionType : 'singleCodeCursor'
selection? : Selection
}
| {
selectionType : 'otherSelection'
selection : Axis
}
| {
selectionType : 'completeSelection'
selection : Selections
}
| {
selectionType : 'mirrorCodeMirrorSelections'
selection : Selections
}
2023-10-16 21:20:05 +11:00
export type ModelingMachineEvent =
| { type : 'Deselect all' }
| { type : 'Deselect edge' ; data : Selection & { type : 'edge' } }
| { type : 'Deselect axis' ; data : Axis }
| {
type : 'Deselect segment'
data : Selection & { type : 'line' | 'arc' }
}
| { type : 'Deselect face' ; data : Selection & { type : 'face' } }
| {
type : 'Deselect point'
data : Selection & { type : 'point' | 'line-end' | 'line-mid' }
}
| { type : 'Enter sketch' }
| { type : 'Select all' ; data : Selection & { type : 'all ' } }
| { type : 'Select edge' ; data : Selection & { type : 'edge' } }
| { type : 'Select axis' ; data : Axis }
| { type : 'Select segment' ; data : Selection & { type : 'line' | 'arc' } }
| { type : 'Select face' ; data : Selection & { type : 'face' } }
| { type : 'Select default plane' ; data : { planeId : string } }
| { type : 'Set selection' ; data : SetSelections }
| {
type : 'Select point'
data : Selection & { type : 'point' | 'line-end' | 'line-mid' }
}
| { type : 'Sketch no face' }
| { type : 'Toggle gui mode' }
| { type : 'Cancel' }
| { type : 'CancelSketch' }
| {
type : 'Add point'
data : {
coords : { x : number ; y : number } [ ]
axis : 'xy' | 'xz' | 'yz' | '-xy' | '-xz' | '-yz' | null
segmentId? : string
}
}
| { type : 'Equip tool' }
| { type : 'Equip move tool' }
| { type : 'Set radius' }
| { type : 'Complete line' }
| { type : 'Set distance' }
| { type : 'Equip new tool' }
| { type : 'update_code' ; data : string }
| { type : 'Make segment horizontal' }
| { type : 'Make segment vertical' }
| { type : 'Constrain horizontal distance' }
| { type : 'Constrain vertical distance' }
| { type : 'Constrain angle' }
| { type : 'Constrain perpendicular distance' }
| { type : 'Constrain horizontally align' }
| { type : 'Constrain vertically align' }
| { type : 'Constrain length' }
| { type : 'Constrain equal length' }
| { type : 'Constrain parallel' }
| { type : 'Constrain remove constraints' }
| { type : 'extrude intent' }
2023-10-18 08:03:02 +11:00
| { type : 'Re-execute' }
2023-10-16 21:20:05 +11:00
2023-10-11 13:36:54 +11:00
export const modelingMachine = createMachine (
{
2023-10-18 08:03:02 +11:00
/ * * @ x s t a t e - l a y o u t N 4 I g p g J g 5 m D O I C 5 Q F k D 2 E w B s C W A 7 K A x A M I C G u A x l g N o A M A u o q A A 6 q z Y A u 2 q u j I A H o g D M A V g D s A O m E i A j L M G C A H I I A s A J l H K A N C A C e i a Q D Z B E s c t G r V A T m m i a N Q Q F 8 H 2 t B h z 5 x 2 C J j A E A y m D s A A S w W G D k n N y 0 D E g g L G y R P L E C C M r C C u L 2 0 q r C R p Y a g v n a e g j Z B t L i B q L p l o I G C t Z V y k 4 u 6 F h 4 U J 7 e v g A i c G E R Q S x 4 7 N G 8 8 R x c S a A p d c K S N K I K i 8 p p w s r L w s X 6 0 o r i q g a W B g b K I m p W q i 0 g r u 0 e X j 4 E f a E + g 5 A w Y 7 E T i b y z x 5 l L u 1 s y g M 6 1 E R V 0 + h o 0 m U 4 g U R l O w i h l i s 2 S u N 3 c n X u v X 6 L 2 C J D 4 2 F g H 2 Y r E m 3 B + Q n M 4 m q d h o y P U I L q B m 2 C A a F T S 5 h o u Q U C M c z m u b Q x X Q e A V x Q 1 Q I 2 J c V J 3 2 S i G U X P E h j B t W k l g a o k M z I h q V U N H E G 0 W g j V q k E U N 2 a M F H W F v l F 4 W C b z A U q + U w p q R o G Q 2 p w a c P W 4 J K J x h g Y U 0 k W u 3 W y m k l r c 1 q x - g G e I J R P o 4 x l r r l q U E q k q d M K O S R N E O L P W G T V h k s w l U 0 O 5 f N a M b u 3 X j Y o A Z i R K M 6 0 + S M w q M g Y 7 G o 6 m b a l C W a I j L C j t J 0 n 3 6 t U F N H b p j G w B R X D s M A A J x C A G t A u Q A B Y d h L p m Y 7 S P i S z A y O X w G F U Q s 0 1 B t X V E E V 9 V S Z r 8 9 G x l d r z c 7 v d D 2 k G I S W P L t T w Q e p B G p E N 8 l D G h V B D L Y d T U f V Z z v Y F Q 3 M S 4 v y t B s H i e B M g l b d s U 0 + T t p n 4 S k 0 K z B R 1 E K d I N G 1 E o z Q q Y x a j y N Q 6 M O B c h T j O 1 B h I T B M C P M l K J S S N o I s E E l l Q r l h G Q k o 9 R h Z E D F U L 1 v W E U M c L r R c b U e H F 7 S C I S R L I 0 C x L d R R 2 R O J Q w Q Q 2 R m M Q E N J D 1 O x j R 5 a E + 1 r A V 6 y X B 4 w D 4 d g N w A V w w I I R j A N d R N l C D l G R J U 6 k f a p K 0 v d Y W S n B Q J E s f J M t O D Y r M - X S + M b A K g t C s B w r - K L g N T M D x P l a w J 0 D K t X N k L l 0 o 2 N j N U L P M P Q 2 H S f L 0 v x d 3 Y A 9 i D I S h M G G w D o p P K j S g 0 f U a D U R F F o V b J 7 x 1 S 9 o O S m Q c l 2 C t R F 4 6 1 p t G - d x F O g 8 A E l G w E 4 J h i i s z p T q t 1 p A a S w L x s c w p F D I x F P l Z Z q X W p R 1 T M U N C s G o V L v O 6 G b p F I j Q i g A B b S L R i e l 1 w P m t 7 s s + 0 R v u N H q 0 p 1 F Q D E q O K D g a B S 9 S O Y 6 P G h i 6 R u u x t C L F B 6 0 Z A 5 6 L I z N 7 c g v S M b D M B U L A f N 7 q T s a S C c L J Z 5 1 w 3 y G c A + W z r h 7 F n i M x G U c e j m M f q 0 o e Q y e i 1 S q K x r H + 1 l S c Q k 5 r D p N q p G E W n O n p 2 G V w A R 2 C 7 A m C C d h U F Q U y t Y o y y u T Y 6 d t M L T z B F H P s l U Q u L 4 K W Z a o 1 l o b G Z h 5 P l Y I Z d X f d o I k d Q A A 3 C q v Z 9 2 b M d m D 0 2 O k 9 R l s j K Q W Q r G F V n K d Z 7 B s n J 7 c V g 9 2 - 3 N O A m C V W I i m Y u d b V M w c z x 4 w t X q R y E D H f V s g U R F D i z M R Z D b x 3 U 8 b Z A S F 3 E I w G R 1 G g n z j d O H I I T B 9 e p C l X W P 7 H w U W - N p K W R z z U Q x c g 9 H 6 7 c T q H k 8 7 t P N + 3 9 X 9 7 7 l Q B u b A A A v b g 7 B T 7 o 3 9 t z M E G R 0 j 2 F U k Y N S F Z 0 q I M q F U e Q V Y l D T i O p - E 6 3 8 n Y P C I N w W A Q U S B 4 C C E A k B 4 C 1 x C S C B A Q k k C K B O m g S 9 W B 1 R J D W A 8 u k J k W Z 0 r 5 H m N l d S Y I 7 I e h l k V A h C s i G + B I b g M h G 4 K G 4 A P p u Y + 9 D G F k I m q w v 2 7 C I I 2 E s P q R E p o l C K H V I h d K 8 9 o K Y U M J G D 0 6 k E 6 S L p o Q 9 e x D S H k M o W Q K A P g z 7 c z h C p e Q d R 7 A H H p J Y B 8 H o J B q g U m I c J e M p C r 2 c Y B N O c i F F K K C D 4 f A 7 B D x s K 5 n o + e G Q T b Q n E a G Y Q l 4 R b q j F n k c w c 5 s g Q 2 - E 4 6 R L j Z F u M U Z Q p g m 4 2 m 4 E Y e Q Y K m A S B b g 0 c w 0 i O i c l Y x p J k D Y P J q 6 F m W q b U 0 l 5 K j c j x v J A c 8 S G m J M b M k 9 x y j q F g I g S Z H Q x k c B Q F w D 4 v R S x S Z K A Q u Y B o a l 6 i m x q f X A W S x E J 2 E v J Y V Z Z 0 f 4 b O a a k w + a j h I H K E t g Y 5 p y s b L C s c t Y 4 t g j Z i H S i I H a j 8 L g i C 0 n C D 5 H c Z H E B + Z Q s A r t 6 H p K g J k 0 F K Q 3 o 2 A N L 6 G F 5 Q p x a B 1 N W e B W l h x 9 i t v Y N F K d 1 m u P k V s o Y f S T L U G y T F M F i I L y X m v N C N Q Y J 0 r H H m F S s E O R T h z I M C y r 5 7 K U m U I 3 G A H O + c g j k C x W u Z M w z + X E r x t m d I a h v Q i C R A o d K C k P q 7 H n o i d 8 5 Q 8 a K o x Q A J T A A A W g C u E Y K 6 4 i X 6 E y h E + w m o 8 b z 0 d a o F k 5 R 9 S Y R 9 F W D i Y J F U A B k 8 A V Q A C r e 0 w O n T O H s N U F 3 T X 6 h A 8 h b 6 S G e Q p S J I Z g S j i U E q L k P U p w l L x r U v C D t v 5 J t w K m 9 N 4 g A A K E o 1 x B A A I I Q A w B A A g A 6 I D i k l H y u a p d g T i F M e k K Q a l T X U p K I i C o N i o S Z T 9 H a 7 y d T m 0 K 1 b e 2 n 2 F 1 d 4 a 2 C K O y A I 7 B 3 j s 1 r V E Z s x E I V E O J l L y Z p C z 1 B Z A O A 0 B x 1 I g n K C G a S i b k 1 B D T U e g I e 9 e 3 n u H S Q p G T A f D r j S c m - N J M J D z 0 W K I F Q N Q c g f q L W 9 D Q k Y g R W D i o B t t w G O 1 g d P f 2 w d F 6 M 5 u w 9 m 2 g A 7 p 7 P N k 6 S 5 C E r v s N 6 k 8 E J H C O C y d y S p s r V z k J T R t c t 6 Y H t I 0 e q 6 u A O A E H z f Y j 6 R o F K a l y N X C N 9 h M h 3 L x i S x E h Z i O H s w O I a T s m q A 1 X I r o + a c z F P I j N I U J Q I J l 2 I E r K T Q o X J 5 5 W E W I s B V + D 6 m f I k y B w z A A 5 V A Q R u 0 j F g J e s d b N 5 N j g + t Y d Q Y I U p 0 n D T q S s M J C k l L p F k R i i q 0 C a o C - G X u C Y B 4 s Z 1 k y L K t Q z Q H A w w Y + + i A N D z F O H 2 Q s q p M o q F y 3 n A z 4 g 8 s V T w C Z 0 r l l M v U i z A c O e B j o R o L + I c G c C p j S n E v B 1 - L H a e u V R M 2 Z 8 y B q h A b C l c a S 8 5 h 6 j W G R O l b I H 1 c i F E K N C O u V h F t d Z W 3 1 9 g c n V D 6 q n U I d I G Q b m m n M L N r y x 2 D G V D h E h M u u w L Q + b 3 Z 8 v t 9 G K H B B 2 b Q y B m A G F M K 0 Z V Z s q A C A Q G 4 G A T w u B c 6 o F 3 O I G A 7 B 3 U w 7 2 Z g d 1 e A U f y b o k I t 8 k Y J m c j q 6 U b K H 0 l j q g Q r p 0 0 h h F U Q 6 h 1 Q 4 B u y 6 H w 4 G U j 8 n q P N w b m A e I W D J B 2 A o 4 3 E j f H g Q i d 8 9 h 0 J M n u A K c D Y z I h A 4 G D C i n D p L N u o A j y g X l i W C K C 6 H j h c 8 h x w F R R 9 s A n 0 F 4 j l h y P U f o 7 b V j n H e O C f u r + Q 7 1 X I v K f y H + + h 5 + U 4 O I W P H P + j n V 5 o T o e t z z v 3 j u E e a J d y L g g Y u J d S 5 l 8 A + X P u k 8 B - V 6 g I P M J k U e e R G k e z F i L D V p y C G T U q l F A J 9 t 5 4 n w r u 0 c Y 8 9 7 j z H P v W 8 e s D 5 r i C i E 9 i o a h X Y O E q C d R V j q L C J o y w N j 1 F O D u p t n d x D c 5 b - g N v 6 f M 8 b k l 7 0 n P c u F e E 7 7 2 r j X z 3 W M I G j v q H I c x 1 T T Z E F P a m E g a 1 + n S F O B C y + x P f 3 X 8 E f F m T 2 - u 6 Y 5 4 B e 4 9 6 K 5 - 7 7 i n 7 F 6 D 6 W b 2 Y X i w Q 5 A h I V p T 4 H D z C 0 h W D H C q Q B r N 6 - 6 R Q E r 7 j t 4 7 5 7 7 S 6 y 5 5 5 g G 4 G Z K Q F B 4 S C W y 3 z Z Q 2 B V i w r I E 1 4 l K X j 1 D L B V B a Q D S 7 q r 4 - 5 D D t K R R d I 9 J 9 I p 6 D K 9 Z F 4 d 4 e 7 A H d 5 H 7 u p t I b g d K C G 9 I b j u p C 4 s K U H Q E p D q A 8 g L B L B n a a h q C P 4 K j z B m i T I l J m i r r Y F 8 H y E C E O 5 C H 9 L O 6 U A E E b j i 6 7 7 Z 4 k E y F y E K G 2 F K E q E O H 9 5 F 4 x b a G r S h r j w G E P g i A S A m G r B m E 1 o O K Q x S J n R B C 4 A h Y k S 2 h E Q Y C t g 9 L 3 S 9 J t r 5 o 1 K n Y V h v T X i T J G A f p T i f R Q h 1 D z x z z m C f 5 6 Q k A 2 6 c D 4 A 7 y 4 h T C F Y t H 2 g l b n 5 D y h z U i 1 a L 7 H D 8 z 3 K q b U h 9 g b D q j P q X g S L x E e A H j h D b g d A d H 9 z c B y Y a H 6 D 4 b 7 C q Y c g H B X J W p q R k q r D m i B K R h t x z H k A L H N F 9 y J B y b r a c y b a l C 0 6 V D G i V w a C g x F g 0 p p D Q T l A 1 Y 2 Y e g I Q 3 a S Y Z p u q e p 8 D e q + p r E F o 8 j Q Q 2 D y A G I A 7 N y j i i z 9 R w h 2 C V g W A H D 6 a A k E D A l e r d L g n d E B w K h k x l q 6 H Q r F j W Y e g g i U z T Y n F X D J E Y D w C x C 7 q 3 r 3 F D i S A y B y C K A q D q C O Y I D u q G D Z g G L W B C x 9 i 2 C
2023-10-11 13:36:54 +11:00
id : 'Modeling' ,
tsTypes : { } as import ( './modelingMachine.typegen' ) . Typegen0 ,
predictableActionArguments : true ,
preserveActionOrder : true ,
context : {
guiMode : 'default' ,
selection : [ ] as string [ ] ,
selectionRanges : {
otherSelections : [ ] ,
codeBasedSelections : [ ] ,
} as Selections ,
selectionRangeTypeMap : { } as SelectionRangeTypeMap ,
sketchPathToNode : null as PathToNode | null , // maybe too specific, and we should have a generic pathToNode, but being specific seems less risky when I'm not sure
sketchEnginePathId : '' as string ,
sketchPlaneId : '' as string ,
} ,
schema : {
2023-10-16 21:20:05 +11:00
events : { } as ModelingMachineEvent ,
2023-10-11 13:36:54 +11:00
} ,
states : {
idle : {
on : {
'Set selection' : {
target : 'idle' ,
internal : true ,
actions : 'Set selection' ,
} ,
'Deselect point' : {
target : 'idle' ,
internal : true ,
actions : [
'Remove from code-based selection' ,
'Update code selection cursors' ,
// 'Engine: remove highlight',
] ,
cond : 'Selection contains point' ,
} ,
'Deselect edge' : {
target : 'idle' ,
internal : true ,
actions : [
'Remove from code-based selection' ,
'Update code selection cursors' ,
// 'Engine: remove highlight',
] ,
cond : 'Selection contains edge' ,
} ,
'Deselect axis' : {
target : 'idle' ,
internal : true ,
actions : [
'Remove from other selection' ,
'Update code selection cursors' ,
// 'Engine: remove highlight',
] ,
cond : 'Selection contains axis' ,
} ,
'Select point' : {
target : 'idle' ,
internal : true ,
actions : [
'Add to code-based selection' ,
'Update code selection cursors' ,
// 'Engine: add highlight',
] ,
} ,
'Select edge' : {
target : 'idle' ,
internal : true ,
actions : [
'Add to code-based selection' ,
'Update code selection cursors' ,
// 'Engine: add highlight',
] ,
} ,
'Select axis' : {
target : 'idle' ,
internal : true ,
actions : [
'Add to other selection' ,
// 'Engine: add highlight',
] ,
} ,
'Select face' : {
target : 'idle' ,
internal : true ,
actions : [
'Add to code-based selection' ,
'Update code selection cursors' ,
// 'Engine: add highlight',
] ,
} ,
'Enter sketch' : [
{
target : 'Sketch' ,
cond : 'Selection is one face' ,
actions : [
'set sketch metadata' ,
'sketch mode enabled' ,
'edit mode enter' ,
] ,
} ,
'Sketch no face' ,
] ,
'Deselect face' : {
target : 'idle' ,
internal : true ,
actions : [
'Remove from code-based selection' ,
'Update code selection cursors' ,
// 'Engine: remove highlight',
] ,
cond : 'Selection contains face' ,
} ,
'Select all' : {
target : 'idle' ,
internal : true ,
actions : 'Add to code-based selection' ,
} ,
'Deselect all' : {
target : 'idle' ,
internal : true ,
actions : [
'Clear selection' ,
'Update code selection cursors' ,
// 'Engine: remove highlight',
] ,
cond : 'Selection is not empty' ,
} ,
'extrude intent' : [
{
target : 'awaiting selection' ,
cond : 'has no selection' ,
} ,
{
target : 'idle' ,
cond : 'has valid extrude selection' ,
internal : true ,
actions : 'AST extrude' ,
} ,
] ,
} ,
} ,
Sketch : {
states : {
SketchIdle : {
on : {
'Select point' : {
target : 'SketchIdle' ,
internal : true ,
actions : [
'Update code selection cursors' ,
'Add to code-based selection' ,
] ,
} ,
'Select segment' : {
target : 'SketchIdle' ,
internal : true ,
actions : [
'Update code selection cursors' ,
'Add to code-based selection' ,
] ,
} ,
'Deselect point' : {
target : 'SketchIdle' ,
internal : true ,
cond : 'Selection contains point' ,
actions : [
'Update code selection cursors' ,
'Add to code-based selection' ,
] ,
} ,
'Deselect segment' : {
target : 'SketchIdle' ,
internal : true ,
cond : 'Selection contains line' ,
actions : [
'Update code selection cursors' ,
'Add to code-based selection' ,
] ,
} ,
'Equip tool' : {
target : 'Line Tool' ,
actions : 'set tool line' ,
} ,
'Equip move tool' : 'Move Tool' ,
'Set selection' : {
target : 'SketchIdle' ,
internal : true ,
actions : 'Set selection' ,
} ,
'Make segment vertical' : {
cond : 'Can make selection vertical' ,
target : 'SketchIdle' ,
internal : true ,
actions : [ 'Make selection vertical' ] ,
} ,
'Make segment horizontal' : {
target : 'SketchIdle' ,
internal : true ,
cond : 'Can make selection horizontal' ,
actions : [ 'Make selection horizontal' ] ,
} ,
'Constrain horizontal distance' : {
target : 'Await horizontal distance info' ,
cond : 'Can constrain horizontal distance' ,
} ,
'Constrain vertical distance' : {
target : 'Await vertical distance info' ,
cond : 'Can constrain vertical distance' ,
} ,
'Constrain angle' : {
target : 'Await angle info' ,
cond : 'Can constrain angle' ,
} ,
'Constrain length' : {
target : 'Await length info' ,
cond : 'Can constrain length' ,
} ,
2023-10-16 08:54:38 +11:00
'Constrain perpendicular distance' : {
target : 'Await perpendicular distance info' ,
cond : 'Can constrain perpendicular distance' ,
} ,
2023-10-11 13:36:54 +11:00
'Constrain horizontally align' : {
cond : 'Can constrain horizontally align' ,
target : 'SketchIdle' ,
internal : true ,
actions : [ 'Constrain horizontally align' ] ,
} ,
'Constrain vertically align' : {
cond : 'Can constrain vertically align' ,
target : 'SketchIdle' ,
internal : true ,
actions : [ 'Constrain vertically align' ] ,
} ,
'Constrain equal length' : {
cond : 'Can constrain equal length' ,
target : 'SketchIdle' ,
internal : true ,
actions : [ 'Constrain equal length' ] ,
} ,
2023-10-16 08:54:38 +11:00
'Constrain parallel' : {
target : 'SketchIdle' ,
internal : true ,
cond : 'Can canstrain parallel' ,
actions : [ 'Constrain parallel' ] ,
} ,
'Constrain remove constraints' : {
target : 'SketchIdle' ,
internal : true ,
cond : 'Can constrain remove constraints' ,
actions : [ 'Constrain remove constraints' ] ,
} ,
2023-10-18 08:03:02 +11:00
'Re-execute' : {
target : 'SketchIdle' ,
internal : true ,
actions : [
'set sketchMetadata from pathToNode' ,
'sketch mode enabled' ,
'edit mode enter' ,
] ,
} ,
2023-10-11 13:36:54 +11:00
} ,
entry : 'equip select' ,
} ,
'Line Tool' : {
states : {
Done : {
type : 'final' ,
} ,
'Point Added' : {
on : {
'Add point' : {
target : 'Segment Added' ,
actions : [ 'AST start new sketch' ] ,
} ,
} ,
} ,
'Segment Added' : {
on : {
'Add point' : {
target : 'Segment Added' ,
internal : true ,
actions : [ 'AST add line segment' ] ,
} ,
'Complete line' : {
target : 'Done' ,
actions : [ 'Modify AST' , 'Update code selection cursors' ] ,
} ,
'Equip new tool' : {
target : 'Segment Added' ,
internal : true ,
actions : 'set tool' ,
} ,
} ,
} ,
Init : {
always : [
{
target : 'Segment Added' ,
cond : 'is editing existing sketch' ,
} ,
'No Points' ,
] ,
} ,
'No Points' : {
on : {
'Add point' : 'Point Added' ,
} ,
} ,
} ,
// invoke: [
// {
// src: 'createLine',
// id: 'Create line',
// onDone: 'SketchIdle',
// },
// ],
initial : 'Init' ,
on : {
'Equip move tool' : 'Move Tool' ,
2023-10-18 08:03:02 +11:00
'Re-execute' : {
target : 'Line Tool' ,
internal : true ,
actions : [
'set sketchMetadata from pathToNode' ,
'sketch mode enabled' ,
'edit mode enter' ,
] ,
} ,
2023-10-11 13:36:54 +11:00
} ,
} ,
'Move Tool' : {
entry : 'set tool move' ,
2023-10-14 03:47:46 +11:00
on : {
'Set selection' : {
target : 'Move Tool' ,
internal : true ,
actions : 'Set selection' ,
} ,
2023-10-18 08:03:02 +11:00
'Re-execute' : {
target : 'Move Tool' ,
internal : true ,
actions : [
'set sketchMetadata from pathToNode' ,
'sketch mode enabled' ,
'edit mode enter' ,
] ,
} ,
2023-10-14 03:47:46 +11:00
} ,
states : {
'Move init' : {
always : [
{
target : 'Move without re-execute' ,
cond : 'can move' ,
} ,
{
target : 'Move with execute' ,
cond : 'can move with execute' ,
} ,
'No move' ,
] ,
} ,
'Move without re-execute' : { } ,
'Move with execute' : { } ,
'No move' : { } ,
} ,
initial : 'Move init' ,
2023-10-11 13:36:54 +11:00
} ,
'Await horizontal distance info' : {
invoke : {
src : 'Get horizontal info' ,
id : 'get-horizontal-info' ,
onDone : {
target : 'SketchIdle' ,
actions : 'Set selection' ,
} ,
onError : 'SketchIdle' ,
} ,
} ,
'Await vertical distance info' : {
invoke : {
src : 'Get vertical info' ,
id : 'get-vertical-info' ,
onDone : {
target : 'SketchIdle' ,
actions : 'Set selection' ,
} ,
onError : 'SketchIdle' ,
} ,
} ,
'Await angle info' : {
invoke : {
src : 'Get angle info' ,
id : 'get-angle-info' ,
onDone : {
target : 'SketchIdle' ,
actions : 'Set selection' ,
} ,
onError : 'SketchIdle' ,
} ,
} ,
'Await length info' : {
invoke : {
src : 'Get length info' ,
id : 'get-length-info' ,
onDone : {
target : 'SketchIdle' ,
actions : 'Set selection' ,
} ,
onError : 'SketchIdle' ,
} ,
} ,
2023-10-16 08:54:38 +11:00
'Await perpendicular distance info' : {
invoke : {
src : 'Get perpendicular distance info' ,
id : 'get-perpendicular-distance-info' ,
onDone : {
target : 'SketchIdle' ,
actions : 'Set selection' ,
} ,
onError : 'SketchIdle' ,
} ,
} ,
2023-10-11 13:36:54 +11:00
} ,
initial : 'SketchIdle' ,
on : {
CancelSketch : '.SketchIdle' ,
} ,
exit : 'sketch exit execute' ,
} ,
'Sketch no face' : {
entry : 'show default planes' ,
exit : 'hide default planes' ,
on : {
'Select default plane' : {
target : 'Sketch' ,
actions : [
'reset sketch metadata' ,
'set default plane id' ,
'sketch mode enabled' ,
'create path' ,
] ,
} ,
} ,
} ,
'awaiting selection' : {
on : {
'Set selection' : {
target : 'checking selection' ,
actions : 'Set selection' ,
} ,
} ,
} ,
'checking selection' : {
always : [
{
target : 'idle' ,
cond : 'has valid extrude selection' ,
actions : 'AST extrude' ,
} ,
{
target : 'idle' ,
actions : 'toast extrude failed' ,
} ,
] ,
} ,
} ,
initial : 'idle' ,
on : {
Cancel : {
target : 'idle' ,
2023-11-01 17:34:54 -05:00
// TODO what if we're existing extrude equipped, should these actions still be fired?
// maybe cancel needs to have a guard for if else logic?
2023-10-11 13:36:54 +11:00
actions : [
'edit_mode_exit' ,
'default_camera_disable_sketch_mode' ,
'reset sketch metadata' ,
] ,
} ,
} ,
} ,
{
guards : {
'is editing existing sketch' : ( { sketchPathToNode } ) = >
! ! sketchPathToNode ,
'Can make selection horizontal' : ( { selectionRanges } ) = >
horzVertInfo ( selectionRanges , 'horizontal' ) . enabled ,
'Can make selection vertical' : ( { selectionRanges } ) = >
horzVertInfo ( selectionRanges , 'vertical' ) . enabled ,
'Can constrain horizontal distance' : ( { selectionRanges } ) = >
horzVertDistanceInfo ( { selectionRanges , constraint : 'setHorzDistance' } )
. enabled ,
'Can constrain vertical distance' : ( { selectionRanges } ) = >
horzVertDistanceInfo ( { selectionRanges , constraint : 'setVertDistance' } )
. enabled ,
'Can constrain angle' : ( { selectionRanges } ) = >
angleBetweenInfo ( { selectionRanges } ) . enabled ,
'Can constrain length' : ( { selectionRanges } ) = >
setAngleLengthInfo ( { selectionRanges } ) . enabled ,
2023-10-16 08:54:38 +11:00
'Can constrain perpendicular distance' : ( { selectionRanges } ) = >
intersectInfo ( { selectionRanges } ) . enabled ,
2023-10-11 13:36:54 +11:00
'Can constrain horizontally align' : ( { selectionRanges } ) = >
horzVertDistanceInfo ( { selectionRanges , constraint : 'setHorzDistance' } )
. enabled ,
'Can constrain vertically align' : ( { selectionRanges } ) = >
horzVertDistanceInfo ( { selectionRanges , constraint : 'setHorzDistance' } )
. enabled ,
'Can constrain equal length' : ( { selectionRanges } ) = >
setEqualLengthInfo ( { selectionRanges } ) . enabled ,
2023-10-16 08:54:38 +11:00
'Can canstrain parallel' : ( { selectionRanges } ) = >
equalAngleInfo ( { selectionRanges } ) . enabled ,
'Can constrain remove constraints' : ( { selectionRanges } ) = >
removeConstrainingValuesInfo ( { selectionRanges } ) . enabled ,
2023-10-11 13:36:54 +11:00
'has no selection' : ( { selectionRanges } ) = > {
if ( selectionRanges ? . codeBasedSelections ? . length < 1 ) return true
const selection = selectionRanges ? . codeBasedSelections ? . [ 0 ] || { }
return (
selectionRanges . codeBasedSelections . length === 1 &&
! hasExtrudeSketchGroup ( {
ast : kclManager.ast ,
programMemory : kclManager.programMemory ,
selection ,
} )
)
} ,
'has valid extrude selection' : ( { selectionRanges } ) = > {
if ( selectionRanges . codeBasedSelections . length !== 1 ) return false
const isSketchPipe = isCursorInSketchCommandRange (
engineCommandManager . artifactMap ,
selectionRanges
)
const common = {
selection : selectionRanges.codeBasedSelections [ 0 ] ,
ast : kclManager.ast ,
}
const hasClose = doesPipeHaveCallExp ( { calleeName : 'close' , . . . common } )
const hasExtrude = doesPipeHaveCallExp ( {
calleeName : 'extrude' ,
. . . common ,
} )
return ! ! isSketchPipe && hasClose && ! hasExtrude
} ,
2023-10-14 03:47:46 +11:00
'can move' : ( { selectionRanges } ) = >
// todo check all cursors are also in the right sketch
selectionRanges . codeBasedSelections . every (
( selection ) = >
getConstraintLevelFromSourceRange (
selection . range ,
kclManager . ast
) === 'free'
) ,
'can move with execute' : ( { selectionRanges } ) = >
// todo check all cursors are also in the right sketch
selectionRanges . codeBasedSelections . every ( ( selection ) = >
[ 'partial' , 'free' ] . includes (
getConstraintLevelFromSourceRange ( selection . range , kclManager . ast )
)
) ,
2023-10-11 13:36:54 +11:00
} ,
actions : {
'Add to code-based selection' : assign ( {
selectionRanges : ( { selectionRanges } , event ) = > ( {
. . . selectionRanges ,
codeBasedSelections : [
. . . selectionRanges . codeBasedSelections ,
event . data ,
] ,
} ) ,
} ) ,
'Add to other selection' : assign ( {
selectionRanges : ( { selectionRanges } , event ) = > ( {
. . . selectionRanges ,
otherSelections : [ . . . selectionRanges . otherSelections , event . data ] ,
} ) ,
} ) ,
'Remove from code-based selection' : assign ( {
selectionRanges : ( { selectionRanges } , event ) = > ( {
. . . selectionRanges ,
codeBasedSelections : [
. . . selectionRanges . codeBasedSelections ,
event . data ,
] ,
} ) ,
} ) ,
'Remove from other selection' : assign ( {
selectionRanges : ( { selectionRanges } , event ) = > ( {
. . . selectionRanges ,
otherSelections : [ . . . selectionRanges . otherSelections , event . data ] ,
} ) ,
} ) ,
'Clear selection' : assign ( {
selectionRanges : ( ) = > ( {
otherSelections : [ ] ,
codeBasedSelections : [ ] ,
} ) ,
} ) ,
'sketch mode enabled' : ( { sketchPlaneId } ) = > {
engineCommandManager . sendSceneCommand ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'sketch_mode_enable' ,
plane_id : sketchPlaneId ,
ortho : true ,
animated : ! isReducedMotion ( ) ,
} ,
} )
} ,
2023-10-18 08:03:02 +11:00
'set sketchMetadata from pathToNode' : assign ( ( { sketchPathToNode } ) = > {
if ( ! sketchPathToNode ) return { }
return getSketchMetadataFromPathToNode ( sketchPathToNode )
} ) ,
2023-10-11 13:36:54 +11:00
'edit mode enter' : ( { selectionRanges } ) = > {
const pathId = isCursorInSketchCommandRange (
engineCommandManager . artifactMap ,
selectionRanges
)
pathId &&
engineCommandManager . sendSceneCommand ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'edit_mode_enter' ,
target : pathId ,
} ,
} )
} ,
2023-10-17 20:08:17 +11:00
'hide default planes' : ( ) = > {
2023-10-11 13:36:54 +11:00
kclManager . hidePlanes ( )
} ,
edit_mode_exit : ( ) = >
engineCommandManager . sendSceneCommand ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : { type : 'edit_mode_exit' } ,
} ) ,
default_camera_disable_sketch_mode : ( ) = >
engineCommandManager . sendSceneCommand ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : { type : 'default_camera_disable_sketch_mode' } ,
} ) ,
'reset sketch metadata' : assign ( {
sketchPathToNode : null ,
sketchEnginePathId : '' ,
sketchPlaneId : '' ,
} ) ,
'set sketch metadata' : assign ( ( { selectionRanges } ) = > {
const sourceRange = selectionRanges . codeBasedSelections [ 0 ] . range
const sketchPathToNode = getNodePathFromSourceRange (
kclManager . ast ,
sourceRange
)
2023-10-18 08:03:02 +11:00
return getSketchMetadataFromPathToNode (
2023-10-11 13:36:54 +11:00
sketchPathToNode ,
2023-10-18 08:03:02 +11:00
selectionRanges
)
2023-10-11 13:36:54 +11:00
} ) ,
'set tool line' : ( ) = >
engineCommandManager . sendSceneCommand ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'set_tool' ,
tool : 'sketch_line' ,
} ,
} ) ,
'equip select' : ( ) = >
engineCommandManager . sendSceneCommand ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'set_tool' ,
tool : 'select' ,
} ,
} ) ,
'set tool move' : ( ) = >
engineCommandManager . sendSceneCommand ( {
type : 'modeling_cmd_req' ,
cmd_id : uuidv4 ( ) ,
cmd : {
type : 'set_tool' ,
tool : 'move' ,
} ,
} ) ,
2023-10-16 08:54:38 +11:00
// TODO implement source ranges for all of these constraints
// need to make the async like the modal constraints
2023-10-11 13:36:54 +11:00
'Make selection horizontal' : ( { selectionRanges } ) = > {
2023-11-01 07:39:31 -04:00
const { modifiedAst } = applyConstraintHorzVert (
2023-10-11 13:36:54 +11:00
selectionRanges ,
'horizontal' ,
kclManager . ast ,
kclManager . programMemory
)
2023-10-16 08:54:38 +11:00
kclManager . updateAst ( modifiedAst , true )
2023-10-11 13:36:54 +11:00
} ,
'Make selection vertical' : ( { selectionRanges } ) = > {
2023-11-01 07:39:31 -04:00
const { modifiedAst } = applyConstraintHorzVert (
2023-10-11 13:36:54 +11:00
selectionRanges ,
'vertical' ,
kclManager . ast ,
kclManager . programMemory
)
2023-10-16 08:54:38 +11:00
kclManager . updateAst ( modifiedAst , true )
2023-10-11 13:36:54 +11:00
} ,
'Constrain horizontally align' : ( { selectionRanges } ) = > {
2023-11-01 07:39:31 -04:00
const { modifiedAst } = applyConstraintHorzVertAlign ( {
2023-10-11 13:36:54 +11:00
selectionRanges ,
constraint : 'setVertDistance' ,
} )
2023-10-16 08:54:38 +11:00
kclManager . updateAst ( modifiedAst , true )
2023-10-11 13:36:54 +11:00
} ,
'Constrain vertically align' : ( { selectionRanges } ) = > {
2023-11-01 07:39:31 -04:00
const { modifiedAst } = applyConstraintHorzVertAlign ( {
2023-10-11 13:36:54 +11:00
selectionRanges ,
constraint : 'setHorzDistance' ,
} )
2023-10-16 08:54:38 +11:00
kclManager . updateAst ( modifiedAst , true )
2023-10-11 13:36:54 +11:00
} ,
'Constrain equal length' : ( { selectionRanges } ) = > {
2023-11-01 07:39:31 -04:00
const { modifiedAst } = applyConstraintEqualLength ( {
2023-10-11 13:36:54 +11:00
selectionRanges ,
} )
2023-10-16 08:54:38 +11:00
kclManager . updateAst ( modifiedAst , true )
} ,
'Constrain parallel' : ( { selectionRanges } ) = > {
2023-11-01 07:39:31 -04:00
const { modifiedAst } = applyConstraintEqualAngle ( {
2023-10-16 08:54:38 +11:00
selectionRanges ,
} )
kclManager . updateAst ( modifiedAst , true )
} ,
'Constrain remove constraints' : ( { selectionRanges } ) = > {
2023-11-01 07:39:31 -04:00
const { modifiedAst } = applyRemoveConstrainingValues ( {
2023-10-16 08:54:38 +11:00
selectionRanges ,
2023-10-11 13:36:54 +11:00
} )
2023-10-16 08:54:38 +11:00
kclManager . updateAst ( modifiedAst , true )
2023-10-11 13:36:54 +11:00
} ,
'AST extrude' : ( { selectionRanges } ) = > {
const pathToNode = getNodePathFromSourceRange (
kclManager . ast ,
selectionRanges . codeBasedSelections [ 0 ] . range
)
const { modifiedAst , pathToExtrudeArg } = extrudeSketch (
kclManager . ast ,
pathToNode
)
// TODO not handling focusPath correctly I think
kclManager . updateAst ( modifiedAst , true , {
focusPath : pathToExtrudeArg ,
} )
} ,
'set default plane id' : assign ( {
sketchPlaneId : ( _ , { data } ) = > data . planeId ,
} ) ,
} ,
}
)
2023-10-18 08:03:02 +11:00
function getSketchMetadataFromPathToNode (
pathToNode : PathToNode ,
selectionRanges? : Selections
) {
const pipeExpression = getNodeFromPath < PipeExpression > (
kclManager . ast ,
pathToNode ,
'PipeExpression'
) . node
if ( pipeExpression . type !== 'PipeExpression' ) return { }
const sketchCallExpression = pipeExpression . body . find (
( e ) = > e . type === 'CallExpression' && e . callee . name === 'startSketchOn'
) as CallExpression
if ( ! sketchCallExpression ) return { }
const firstArg = sketchCallExpression . arguments [ 0 ]
let planeId = ''
if ( firstArg . type === 'Literal' && firstArg . value ) {
const planeStrCleaned = firstArg . value
. toString ( )
. toLowerCase ( )
. replace ( '-' , '' )
if (
planeStrCleaned === 'xy' ||
planeStrCleaned === 'xz' ||
planeStrCleaned === 'yz'
) {
planeId = kclManager . getPlaneId ( planeStrCleaned )
}
}
let sketchEnginePathId : string
if ( selectionRanges ) {
sketchEnginePathId =
isCursorInSketchCommandRange (
engineCommandManager . artifactMap ,
selectionRanges
) || ''
} else {
const _selectionRanges : Selections = {
otherSelections : [ ] ,
codeBasedSelections : [
{ range : [ pipeExpression . start , pipeExpression . end ] , type : 'default' } ,
] ,
}
sketchEnginePathId =
isCursorInSketchCommandRange (
engineCommandManager . artifactMap ,
_selectionRanges
) || ''
}
console . log ( 'returning:' , {
sketchPathToNode : pathToNode ,
sketchEnginePathId ,
sketchPlaneId : planeId ,
} )
return {
sketchPathToNode : pathToNode ,
sketchEnginePathId ,
sketchPlaneId : planeId ,
}
}