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'
2023-12-01 20:18:51 +11:00
import { angleLengthInfo } from 'components/Toolbar/setAngleLength'
2023-10-11 13:36:54 +11:00
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-12-01 20:18:51 +11:00
import {
absDistanceInfo ,
applyConstraintAxisAlign ,
} from 'components/Toolbar/SetAbsDistance'
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' }
2023-12-01 20:18:51 +11:00
| { type : 'Constrain ABS X' }
| { type : 'Constrain ABS Y' }
2023-10-16 21:20:05 +11:00
| { type : 'Constrain vertical distance' }
| { type : 'Constrain angle' }
| { type : 'Constrain perpendicular distance' }
| { type : 'Constrain horizontally align' }
| { type : 'Constrain vertically align' }
2023-12-01 20:18:51 +11:00
| { type : 'Constrain snap to X' }
| { type : 'Constrain snap to Y' }
2023-10-16 21:20:05 +11:00
| { 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-12-01 20:18:51 +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 Q c w H G N L t E c O o q x i A v L O d S V 4 c E y y K g Q h W R D f A k N w G Q j c F D c A H 0 3 M f e h j C y E T V Y X 7 d h E E b C W H 1 F p H h I h y j A i n n q E Q B p j A 9 i W F Y W + 4 j I a S L O j - R s s j 5 G K K C A A Q Q A E J + C C A A D T P t z Z Y p N s p L D q P P Z U i g H y a l J p l W k C p j S H C q K v Q h 6 9 i G k P I Z Q 7 x v i A C a g T d H B N h A h D S d R 7 B 0 Q f P P G i m U X z Q m B H g i R d N U m A T T q 4 z J S i y B Q B 8 P k r G c I V K r C n M t d 8 f Z 7 6 I G k h 9 G w b 0 o R j h y K a F J U i 0 k y I y Q o y h P h 8 D s E P G w r m B T 0 g X h y K q L k B x 8 j h 3 4 Y o N C 3 F r y I l y H M p x 0 j i B L P c U w T c j z c C M P I M F T A J A t z q O Y a R b R W y s Y 0 k y M I I 4 K g s w W A H A + M Q p M j D G i r K I V i m p r k d 1 u a 0 5 Z S j q F g I g S Z H Q x k c B Q F w N 0 l I N g 4 S w j N O o R C R w K a m 2 y K s A 0 A s b H L D p H F J F K d m k u P u Z Q w + q j h I 4 q E t g f F h L 9 D L G g g q U x t g j Z i H S i I H a j 8 L g i C 0 n C F l z j 0 l y L a S E X A J A P Z e 3 8 Y K 3 W x h 9 j y q O C l e C C h 0 p 4 3 1 C o c w c F 0 g J P s d + R p 8 y 2 U q r c Z Q 2 A G q t W o C C H k z Z M U e n 6 u W i G A 5 m U j W W H S p l e Y V R 7 C 5 G B N l G m + C H U 3 I W X c 1 V a K g h g F d v Q 1 Z U B 1 m 6 r e j Y A 0 v o J X l C n F o H U 1 Z 4 F a W H H 2 K 2 9 g l U o o 5 U o p g n y T L U B 9 X N I l l S L y X m v L U 9 Q o a y 3 H H m C W s E O R T i m j j Q 0 h 2 T S l b s p T e 4 j c Y A c 7 5 y C O Q B t 7 B k x - N 9 U S v G 2 Y b X q U U C I J E p q y 0 K X G Y o B S d J 5 7 l D x n W p N A A l M A A B a A K 4 R g r r l z d U p U 9 h N R 4 y v T Y V Q L J y j 6 k w j 6 K s H E w R K o A D J 4 A q g A F W 9 p g d O m c P Z L o L g h 3 V 8 h b 6 S B s Q p N U 6 R P K j i U F + h e x p T 1 4 w h v a q d C t o O 4 D g w h g g D 7 n 1 8 F f e + t t J c h D L T Q h c z K 8 9 x X F g + n S D 0 I J K Z J M j F B m D Q R 4 M + 3 E A A B Q l G u T x E A M A Q A I B 4 p T 4 p J R s Z 1 m a Y E 4 h F A V n n o l N Q q x i x Q i V C c K E 4 a 4 r z y k O J 2 j k m E M X V 3 h r Y I a n l O q f U 2 z D D i E K i H E y l 5 M 0 h Z 6 g s g H A a A 4 6 k Q T l B D N J O z d H p M B D 3 g p t z k A 7 l I y Y D 4 d c Q R 3 B a N q v 8 2 Y d T Y S r X h W k B o O Q Q t Y b e h o S M Q I r D M v j V R p x N G 4 u Y C c 4 l 1 z S m U s Z z d h 7 W j A B 3 T 2 6 G t O W U 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 C j e E G s d y a w 5 6 T V 1 c A c A I L q 9 S a p - j y s 1 N G q c g H 7 C Z H q G I T U S E 7 A G F i + t l r m 3 t t U B q u R H R 8 1 x 0 C e R G a Q o S g Q S l p K J W U m h Q u T z y s I s R Y t 3 6 u d 3 E G t q T L W A B y n q 5 M j F g B 5 i A G n N a 5 a 3 a M s c H 1 r D q D B C l O k A G d S V h h N C L k + j 9 G k c y k q t A y 6 4 f x l 7 g m A e Q 2 M x M i y r U M l 8 J g W L F H G k S x f Z C y q k y i o O n e d m s M a f S + t 5 r H N 3 t q E D y a C N h 5 D 6 L h M K q e V 2 C 0 W z s J W C w B x x c M 8 c - T i q e A n t s 4 g i I f R 1 I w X l A p V C f 7 k I - h J M L A k 6 E h Q l t y 3 p i b + 7 4 g f d m - Y D t l 7 5 l s c I B U P P B K w 9 z D 1 G s M i d K 2 Q P q 5 E K I U a E d c r C G + a 3 7 i X l U n u q H l + x s P 6 Q M g N D U s Y d S z d 7 D x + t 5 P a 7 I Z d g W i h - T D x v W K H B A x b Q y B m A G F M M 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 H 3 t 6 x Z g R 9 e B + + 7 e 4 p k K W i S v L T h F s 5 M c f Y w Y a H y B O h x C a O 7 N 9 b 1 Q 4 B m K 6 F d + + b 3 p f A - N w b m A e I d L J B 2 D 9 4 3 E j K f g R Z + X 4 7 0 J R f X A Z f C 3 d 7 V f J o e F L M S L T U R 3 B A K s U 4 C 8 K Q O i B E P W U 4 J V M - D g Z R I + b A E + G - H v F h P v A f I f W j U f c f S f a f R 9 L l b A g A + - F f e Q S o d U X Y C w c N D Q B 8 Z a e Y a W M w c o R Q S m N A l v D A y g n A 7 v D R f A + - A g R - Z - V - d - Y B L - c g g Q 6 g o A 1 A W g m E J k M u O k N S A R V g 5 a f 4 W + b h S 8 c 0 D + S d a H d A 1 z H x f x A g w f Y f E g i f E f c g k g A A I 1 g E f T 4 E A O A P z x 1 k Q j 2 D B S z G q 0 K H K G i X U i B T q F F Q P Q M O P x W 3 O m M M 8 V M L 8 X M P E I 3 B f w + S k M - 2 - x n 3 s M c O c J o J A J S A 8 I y D m z 1 F w 2 J 3 7 S U i q H 1 i u z x j a j M A G k o y M L 4 J M N y X M K I J H z w F I J s J - z S M f R 0 B c M U K y N G V s k + m G V k n y A U m P S U j o g + k j D h R K 2 q X q T C J q P P 2 y S 9 V i I 3 C f 3 i M k I - x k L a I c I 6 K 6 N o P g W D W B T G 3 M H k A f G R H m H V E Q j h B y F s A r F 4 P P w 6 R 8 A a M s O a O s J S M f X u K f U y L c L d B y N h B M W X m F V o g f B m y V 2 + k M C n G s F u I w P e K W J W I S L f 3 W N e P e J 2 J 6 N g J 5 H 1 A O F W E R H j n o h g I s D B E y A O D B B W j U l C O q K b 1 q K y 0 i m z X 3 E e O I O e L I J - y z X W W R K + I z A 8 J C W R B i S Z R t Q f A b g v D H H W F 2 C a D O E h O C C Z J
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' ,
} ,
2023-12-01 20:18:51 +11:00
'Constrain ABS X' : {
target : 'Await ABS X info' ,
cond : 'Can constrain ABS X' ,
} ,
'Constrain ABS Y' : {
target : 'Await ABS Y info' ,
cond : 'Can constrain ABS Y' ,
} ,
2023-10-11 13:36:54 +11:00
'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' ] ,
} ,
2023-12-01 20:18:51 +11:00
'Constrain snap to X' : {
cond : 'Can constrain snap to X' ,
target : 'SketchIdle' ,
internal : true ,
actions : [ 'Constrain snap to X' ] ,
} ,
'Constrain snap to Y' : {
cond : 'Can constrain snap to Y' ,
target : 'SketchIdle' ,
internal : true ,
actions : [ 'Constrain snap to Y' ] ,
} ,
2023-10-11 13:36:54 +11:00
'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' ,
} ,
} ,
2023-12-01 20:18:51 +11:00
'Await ABS X info' : {
invoke : {
src : 'Get ABS X info' ,
id : 'get-abs-x-info' ,
onDone : {
target : 'SketchIdle' ,
actions : 'Set selection' ,
} ,
onError : 'SketchIdle' ,
} ,
} ,
'Await ABS Y info' : {
invoke : {
src : 'Get ABS Y info' ,
id : 'get-abs-y-info' ,
onDone : {
target : 'SketchIdle' ,
actions : 'Set selection' ,
} ,
onError : 'SketchIdle' ,
} ,
} ,
2023-10-11 13:36:54 +11:00
'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 ,
2023-12-01 20:18:51 +11:00
'Can constrain ABS X' : ( { selectionRanges } ) = >
absDistanceInfo ( { selectionRanges , constraint : 'xAbs' } ) . enabled ,
'Can constrain ABS Y' : ( { selectionRanges } ) = >
absDistanceInfo ( { selectionRanges , constraint : 'yAbs' } ) . enabled ,
2023-10-11 13:36:54 +11:00
'Can constrain angle' : ( { selectionRanges } ) = >
2023-12-01 20:18:51 +11:00
angleBetweenInfo ( { selectionRanges } ) . enabled ||
angleLengthInfo ( { selectionRanges , angleOrLength : 'setAngle' } ) . enabled ,
2023-10-11 13:36:54 +11:00
'Can constrain length' : ( { selectionRanges } ) = >
2023-12-01 20:18:51 +11:00
angleLengthInfo ( { 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 ,
2023-12-01 20:18:51 +11:00
'Can constrain snap to X' : ( { selectionRanges } ) = >
absDistanceInfo ( { selectionRanges , constraint : 'snapToXAxis' } ) . enabled ,
'Can constrain snap to Y' : ( { selectionRanges } ) = >
absDistanceInfo ( { selectionRanges , constraint : 'snapToYAxis' } ) . enabled ,
2023-10-11 13:36:54 +11:00
'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
} ,
2023-12-01 20:18:51 +11:00
'Constrain snap to X' : ( { selectionRanges } ) = > {
const { modifiedAst } = applyConstraintAxisAlign ( {
selectionRanges ,
constraint : 'snapToXAxis' ,
} )
kclManager . updateAst ( modifiedAst , true )
} ,
'Constrain snap to Y' : ( { selectionRanges } ) = > {
const { modifiedAst } = applyConstraintAxisAlign ( {
selectionRanges ,
constraint : 'snapToYAxis' ,
} )
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 ,
}
}