Skip to content

CSE UI/UX: Animations & UI improvements #2931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 156 commits into from
Apr 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
156 commits
Select commit Hold shift + click to select a range
ce678d5
display array indices
notnotmax Jan 24, 2024
b45bd17
animate moving numbers from agenda to stash
notnotmax Jan 26, 2024
00d78a4
add code to read from previous agenda
notnotmax Jan 29, 2024
1fb3b0d
Add animation components and some abstraction
CZX123 Feb 3, 2024
688582a
Change test cases
CZX123 Feb 3, 2024
e8cc8cd
Fix bug
notnotmax Feb 4, 2024
edf9672
display array indices
notnotmax Jan 24, 2024
a81d1a4
animate moving numbers from agenda to stash
notnotmax Jan 26, 2024
d08ebf8
add code to read from previous agenda
notnotmax Jan 29, 2024
45abe04
Add animation components and some abstraction
CZX123 Feb 3, 2024
c2357eb
Change test cases
CZX123 Feb 3, 2024
c936fed
Fix bug
notnotmax Feb 4, 2024
26e2311
Fix issues with names after rebase
CZX123 Feb 6, 2024
64a8c2d
Fix animation bugs and refactoring of animation classes and logic
CZX123 Feb 7, 2024
efa8c57
Fix mistake in test snapshot
CZX123 Feb 7, 2024
7ef87d8
Merge branch 'cse-uiux' of https://github.com/source-academy/frontend…
notnotmax Feb 7, 2024
bf886ac
Revert "Merge branch 'cse-uiux' of https://github.com/source-academy/…
notnotmax Feb 7, 2024
20cd2b2
Restructure animation classes
notnotmax Feb 9, 2024
53c3189
Add binary operator animation
notnotmax Feb 9, 2024
e352a14
Add unary operator animation
notnotmax Feb 10, 2024
c0076b2
Begin work on block separation animation
notnotmax Feb 10, 2024
a8f0aa9
Improve binary operation animation, and improve the versatility of th…
CZX123 Feb 10, 2024
1beba43
Resolve merge conflicts
CZX123 Feb 10, 2024
415ef6b
Improve the unary operation and block animations
CZX123 Feb 10, 2024
344586a
Merge branch 'master' into cse-uiux
CZX123 Feb 11, 2024
01c1a94
Update test cases and remove block animation conditions
CZX123 Feb 11, 2024
d1236f6
Add pop animation (linear movement)
notnotmax Feb 11, 2024
7474a07
Improve pop animation, and cleanup code for pull request
CZX123 Feb 12, 2024
4011e03
Merge branch 'master' into cse-uiux
CZX123 Feb 12, 2024
87f58b7
Revert envVisualizer test snapshot changes
CZX123 Feb 12, 2024
e21272d
Merge branch 'master' into cse-uiux
RichDom2185 Feb 13, 2024
bdf3047
Merge branch 'master' into cse-uiux
CZX123 Feb 14, 2024
f73bab8
Add assignment animation
notnotmax Feb 16, 2024
6d8f86e
Work on binding lookup function
notnotmax Feb 16, 2024
11b4034
Improve assignment animation and touch up on other animations, added …
CZX123 Feb 17, 2024
e167193
Add lookup animation (Identifier)
notnotmax Feb 18, 2024
6338434
Improve lookup animation
CZX123 Feb 19, 2024
ea07d0c
Hide arrows for lookup animation and show them when it's finished
CZX123 Feb 19, 2024
9c3471f
Merge remote-tracking branch 'origin' into cse-uiux2
notnotmax Feb 21, 2024
f5916bf
Remove AnimationUtils.tsx file
notnotmax Feb 21, 2024
dc702a3
Slow down assignment and lookup animations
notnotmax Feb 21, 2024
3bf3e3c
Merge branch 'master' into cse-uiux2
notnotmax Feb 23, 2024
92b96ba
Merge branch 'master' into cse-uiux2
CZX123 Mar 8, 2024
92e42f1
Fix issues with merging
CZX123 Mar 8, 2024
d173d25
Add environment animation
notnotmax Mar 10, 2024
bbe0819
Refactor setDestination and animate to new method animateTo
CZX123 Mar 14, 2024
fe55de2
Improve env animation and rename a utility function
CZX123 Mar 14, 2024
147121d
Added animated arrows and also modified GenericArrow and improve assi…
CZX123 Mar 14, 2024
b0ebe62
Update test snapshot and formatting changes
CZX123 Mar 14, 2024
882d144
Add arrow animation to lookup animation, and fix animateTo function b…
CZX123 Mar 14, 2024
09ded36
Add FrameCreationAnimation
notnotmax Mar 14, 2024
412885e
Rewrote all animation components for greater flexibility and performance
CZX123 Mar 15, 2024
53064a7
Shorten duration and delay names, and add listener functionality
CZX123 Mar 16, 2024
ee4e95d
Move experimental file
CZX123 Mar 16, 2024
eb018ad
Fix issues with `this` keyword
CZX123 Mar 16, 2024
806819f
Rewrite AnimatedTextbox to make it easier for both Text and Rect with…
CZX123 Mar 16, 2024
4019719
Improve FrameCreationAnimation and bunch of other fixes
CZX123 Mar 16, 2024
129c807
Fix some issues with `undefined` inside the control and stash
CZX123 Mar 16, 2024
71e090c
Merge branch 'master' into cse-uiux2
CZX123 Mar 16, 2024
04035bc
Make compact components the new default and remove any mentions to th…
CZX123 Mar 17, 2024
64663e2
Update test snapshots
CZX123 Mar 17, 2024
fd52429
Merge branch 'master' into cse-component-refactor
CZX123 Mar 17, 2024
6c004c1
Clean up testing code a little
CZX123 Mar 17, 2024
c59e403
Formatting changes
CZX123 Mar 17, 2024
79ee4b9
Merge branch 'master' into cse-uiux2
CZX123 Mar 17, 2024
b0e5852
Merge branch 'cse-component-refactor' into cse-uiux2
CZX123 Mar 17, 2024
39f8964
Fix issues after merge
CZX123 Mar 17, 2024
bd5880a
Merge branch 'master' into cse-uiux2
CZX123 Mar 17, 2024
6c23bd0
Revert some incorrect merges
CZX123 Mar 17, 2024
f83d166
Add FunctionFrameCreationAnimation
notnotmax Mar 17, 2024
a79ad06
Add getNodeDimensions and getNodeLocation
notnotmax Mar 17, 2024
da18eed
Add ArrowFunctionExpressionAnimation
notnotmax Mar 17, 2024
48ad16d
Add BranchAnimation
notnotmax Mar 17, 2024
c6e1ecc
Sort instr types in alphabetical order
notnotmax Mar 17, 2024
dc9abae
Add ArrayLiteralAnimation
notnotmax Mar 17, 2024
7f98be6
Added cases for block splitting
notnotmax Mar 17, 2024
3dabe6b
Improve animations for arrow functions and branch instruction
CZX123 Mar 18, 2024
7c43faa
Update function application animation
CZX123 Mar 18, 2024
a491702
Merge branch 'master' into cse-uiux2
CZX123 Mar 21, 2024
4a828b0
Special changes for js-slang branch: add new objectCount property and…
CZX123 Mar 21, 2024
00b390d
Change dummy binding behavior to match js-slang update
CZX123 Mar 22, 2024
4308240
Fix array references being lost in frames due to cloning property des…
CZX123 Mar 23, 2024
4b04191
Simplify code
CZX123 Mar 23, 2024
3b89c14
Merge branch 'master' into cse-uiux2
CZX123 Mar 23, 2024
fceb10a
Add ArrayAccessAnimation
notnotmax Mar 24, 2024
c3a1ee0
Begin work on ArrayAssignmentAnimation
notnotmax Mar 25, 2024
f2a93fa
Fix application animation for predeclared funcs
notnotmax Mar 25, 2024
ba00300
Changes to solve issue 2700 and some fixes regarding global frame
CZX123 Mar 25, 2024
2c0a4e8
Merge branch 'cse-uiux2' of https://github.com/source-academy/fronten…
CZX123 Mar 25, 2024
c50eaa4
Re-add animations
CZX123 Mar 25, 2024
0efc090
Merge branch 'master' into cse-uiux2
CZX123 Mar 25, 2024
fd5bd17
Fix many issues regarding displaying objects on global frame
CZX123 Mar 26, 2024
f11590d
Formatting
CZX123 Mar 26, 2024
be7c302
Simplify merging of environment heaps and drawing of bindings
CZX123 Mar 27, 2024
b188254
Fix infinite loop in `findObjects`
CZX123 Mar 27, 2024
91fac72
Merge branch 'master' into cse-uiux2
CZX123 Mar 27, 2024
91056c4
Merge branch 'master' into cse-uiux2
CZX123 Mar 29, 2024
7a4cee7
Disable animations if control is truncated
notnotmax Mar 31, 2024
f2e7f96
Fix AssignmentAnimation
notnotmax Mar 31, 2024
3141d53
Increase space between closure and frame
notnotmax Mar 31, 2024
9498cb2
Change for/while instr to use BranchAnimation
notnotmax Mar 31, 2024
0b9492c
Initial Commit
CZX123 Apr 7, 2024
f60377f
Merge branch 'master' into cse-envfix
CZX123 Apr 7, 2024
885f7ca
More fixes and added faded gc objects
CZX123 Apr 7, 2024
1ab534f
Merge branch 'master' into cse-uiux2
notnotmax Apr 7, 2024
6572986
Disable variadic function animation
notnotmax Apr 7, 2024
d060993
Increase spacing for global closure
notnotmax Apr 7, 2024
3d6e46a
Add missing case 'FunctionExpression'
notnotmax Apr 7, 2024
028d674
Fix variadic function checker
notnotmax Apr 7, 2024
9327a92
Improve FunctionApplicationAnimation
notnotmax Apr 7, 2024
5a8b8d5
Improve assignment animation
notnotmax Apr 7, 2024
d8c346f
Merge branch 'master' into cse-envfix
CZX123 Apr 7, 2024
c1eefad
Run format
CZX123 Apr 8, 2024
15e0606
Merge branch 'master' into cse-envfix
CZX123 Apr 8, 2024
ee9eda3
Simplify check frame creation
notnotmax Apr 8, 2024
c49f3c2
Fix params text and added SourceObject to display runes correctly
CZX123 Apr 8, 2024
33f8ed6
bumping js-slang
martin-henz Apr 9, 2024
255dd70
Merge branch 'master' into cse-envfix
martin-henz Apr 9, 2024
c814cd9
Revamp unreferenced behavior and update snapshots
CZX123 Apr 9, 2024
0d6202c
Run format
CZX123 Apr 9, 2024
e869039
Merge branch 'master' into cse-envfix
CZX123 Apr 9, 2024
bd82d0b
Update snapshot
CZX123 Apr 9, 2024
d04a238
Bump js-slang
CZX123 Apr 9, 2024
d738da6
Merge branch 'master' into cse-uiux2
CZX123 Apr 9, 2024
62b5e8b
Merge branch 'cse-envfix' into cse-uiux2
CZX123 Apr 9, 2024
41b5cbc
Fix issues after merge
CZX123 Apr 9, 2024
94e2bf9
Merge branch 'master' into cse-uiux2
CZX123 Apr 10, 2024
4c380b2
Merge branch 'master' into cse-uiux2
notnotmax Apr 10, 2024
ca77d5f
Fix frames creeping to the left
notnotmax Apr 10, 2024
62cf488
Improve rune display, revamp color system and add color interpolation
CZX123 Apr 10, 2024
93d7e28
Merge branch 'cse-uiux2' of https://github.com/source-academy/fronten…
CZX123 Apr 10, 2024
7ac4058
UI & animation improvements
CZX123 Apr 11, 2024
29d6e40
Big improvements for many animations
CZX123 Apr 11, 2024
316c9cc
More improvements, better transitions between border colors
CZX123 Apr 12, 2024
2c068ec
More improvements and update snapshot
CZX123 Apr 13, 2024
f7b9f64
Merge branch 'master' into cse-uiux2
CZX123 Apr 13, 2024
51e1cab
Merge branch 'master' into cse-uiux2
martin-henz Apr 13, 2024
51fd03f
Update types
RichDom2185 Apr 13, 2024
0c4c58a
Remove explicit fragment
RichDom2185 Apr 13, 2024
f38cb7e
Remove explicit fragment again
RichDom2185 Apr 13, 2024
ba128e4
Update typings
RichDom2185 Apr 13, 2024
ec8d42f
Merge branch 'cse-uiux2' of https://github.com/source-academy/fronten…
notnotmax Apr 13, 2024
b61de48
Merge branch 'master' into cse-uiux2
RichDom2185 Apr 13, 2024
7fb9bf1
Fix findObjects
notnotmax Apr 13, 2024
f248083
Add docs
notnotmax Apr 13, 2024
b720f78
Re-add color dependencies for Java CSE
notnotmax Apr 13, 2024
e6e00fa
Merge branch 'master' into cse-uiux2
RichDom2185 Apr 13, 2024
65ff844
Re-add color dependencies for Java CSE
RichDom2185 Apr 13, 2024
4fdc62b
Fix format
RichDom2185 Apr 13, 2024
658d9df
Merge branch 'master' of https://github.com/source-academy/frontend i…
RichDom2185 Apr 13, 2024
ec108b7
Array access & asgn animation improvements, general polish
CZX123 Apr 13, 2024
393126a
Merge branch 'cse-uiux2' of https://github.com/source-academy/fronten…
CZX123 Apr 13, 2024
a8dd978
Cleanup and update java cse machine colors to use new functions
CZX123 Apr 13, 2024
f433c67
Move type helpers from animation utils to global type helpers file
CZX123 Apr 13, 2024
83a53f8
Run format
CZX123 Apr 13, 2024
03cb5b0
Fix fn to frame arrow, and cleanup arrow code
CZX123 Apr 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/commons/utils/JsSlangHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export function visualizeCseMachine({ context }: { context: Context }) {
CseMachine.drawCse(context);
} catch (err) {
console.error(err);
throw new Error('CSE machine is not enabled');
}
}

Expand Down
16 changes: 16 additions & 0 deletions src/commons/utils/TypeHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@ export type ActionType<T extends Record<string, any>> = {
[k in keyof T]: ReturnType<T[k]>;
}[keyof T];

/** Omits the index signature `[key: string]: any;` from type `T` */
export type RemoveIndex<T> = {
[K in keyof T as string extends K
? never
: number extends K
? never
: symbol extends K
? never
: K]: T[K];
};

/** A true intersection of the properties of types `A` and `B`, unlike the confusingly named
* "Intersection Types" in TypeScript which uses the `&` operator and are actually unions.
* This also excludes the index signature from both `A` and `B` automatically. */
export type SharedProperties<A, B> = Pick<A, Extract<keyof RemoveIndex<A>, keyof RemoveIndex<B>>>;

/* =========================================
* Utility types for tuple type manipulation
* ========================================= */
Expand Down
306 changes: 244 additions & 62 deletions src/features/cseMachine/CseMachineAnimation.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,44 @@
import { InstrType } from 'js-slang/dist/cse-machine/types';
import { AppInstr, ArrLitInstr, AssmtInstr, InstrType } from 'js-slang/dist/cse-machine/types';
import { Node } from 'js-slang/dist/types';
import { Layer } from 'konva/lib/Layer';
import { Easings } from 'konva/lib/Tween';
import React from 'react';

import { Animatable } from './animationComponents/AnimationComponents';
import { ArrayAccessAnimation } from './animationComponents/ArrayAccessAnimation';
import { ArrayAssignmentAnimation } from './animationComponents/ArrayAssignmentAnimation';
import { AssignmentAnimation } from './animationComponents/AssignmentAnimation';
import { Animatable } from './animationComponents/base/Animatable';
import { lookupBinding } from './animationComponents/base/AnimationUtils';
import { BinaryOperationAnimation } from './animationComponents/BinaryOperationAnimation';
import { BlockAnimation } from './animationComponents/BlockAnimation';
import { LiteralAnimation } from './animationComponents/LiteralAnimation';
import { BranchAnimation } from './animationComponents/BranchAnimation';
import { ControlExpansionAnimation } from './animationComponents/ControlExpansionAnimation';
import { ControlToStashAnimation } from './animationComponents/ControlToStashAnimation';
import { EnvironmentAnimation } from './animationComponents/EnvironmentAnimation';
import { FrameCreationAnimation } from './animationComponents/FrameCreationAnimation';
import { FunctionApplicationAnimation } from './animationComponents/FunctionApplicationAnimation';
import { InstructionApplicationAnimation } from './animationComponents/InstructionApplicationAnimation';
import { LookupAnimation } from './animationComponents/LookupAnimation';
import { PopAnimation } from './animationComponents/PopAnimation';
import { UnaryOperationAnimation } from './animationComponents/UnaryOperationAnimation';
import { isInstr } from './components/ControlStack';
import { isNode } from './components/ControlStack';
import { Frame } from './components/Frame';
import { ArrayValue } from './components/values/ArrayValue';
import CseMachine from './CseMachine';
import { Layout } from './CseMachineLayout';
import { isBuiltInFn, isStreamFn } from './CseMachineUtils';

export class CseAnimation {
private static animationEnabled = false;
static readonly animationComponents: Animatable[] = [];
static readonly defaultDuration = 0.3;
static readonly animations: Animatable[] = [];
static readonly defaultDuration = 300;
static readonly defaultEasing = Easings.StrongEaseInOut;
private static animationEnabled = false;
private static currentFrame: Frame;
private static previousFrame: Frame;

static layerRef = React.createRef<Layer>();
static getLayer(): Layer | null {
return this.layerRef.current;
}

static enableAnimations(): void {
CseAnimation.animationEnabled = true;
Expand All @@ -25,99 +48,258 @@ export class CseAnimation {
CseAnimation.animationEnabled = false;
}

static setCurrentFrame(frame: Frame) {
CseAnimation.previousFrame = CseAnimation.currentFrame;
CseAnimation.currentFrame = frame;
}

private static clearAnimationComponents(): void {
CseAnimation.animationComponents.length = 0;
CseAnimation.animations.length = 0;
}

private static getNewControlItems() {
const currentControlSize = Layout.controlComponent.control.size();
const previousControlSize = Layout.previousControlComponent.control.size();
const numOfItems = currentControlSize - previousControlSize + 1;
if (numOfItems <= 0) return [];
return Layout.controlComponent.stackItemComponents.slice(-numOfItems);
}

private static handleNode(node: Node) {
const lastControlComponent = Layout.previousControlComponent.stackItemComponents.at(-1)!;
const currStashComponent = Layout.stashComponent.stashItemComponents.at(-1)!;
switch (node.type) {
case 'Program':
CseAnimation.animations.push(
new ControlExpansionAnimation(lastControlComponent, CseAnimation.getNewControlItems())
);
if (CseMachine.getCurrentEnvId() !== '-1') {
CseAnimation.animations.push(
new FrameCreationAnimation(lastControlComponent, CseAnimation.currentFrame)
);
}
break;
case 'BlockStatement':
CseAnimation.animations.push(
new ControlExpansionAnimation(lastControlComponent, CseAnimation.getNewControlItems()),
new FrameCreationAnimation(lastControlComponent, CseAnimation.currentFrame)
);
break;
case 'Literal':
CseAnimation.animations.push(
new ControlToStashAnimation(lastControlComponent, currStashComponent!)
);
break;
case 'ArrowFunctionExpression':
CseAnimation.animations.push(
new ControlToStashAnimation(lastControlComponent, currStashComponent!)
);
break;
case 'Identifier':
// Special case for 'undefined' identifier
if (node.name === 'undefined') {
CseAnimation.animations.push(
new ControlToStashAnimation(lastControlComponent, currStashComponent!)
);
} else {
CseAnimation.animations.push(
new LookupAnimation(
lastControlComponent,
currStashComponent!,
...lookupBinding(CseAnimation.currentFrame, node.name)
)
);
}
break;
case 'AssignmentExpression':
case 'ArrayExpression':
case 'BinaryExpression':
case 'CallExpression':
case 'ConditionalExpression':
case 'ForStatement':
case 'IfStatement':
case 'MemberExpression':
case 'ReturnStatement':
case 'StatementSequence':
case 'UnaryExpression':
case 'VariableDeclaration':
case 'FunctionDeclaration':
case 'WhileStatement':
CseAnimation.animations.push(
new ControlExpansionAnimation(lastControlComponent, CseAnimation.getNewControlItems())
);
break;
case 'ExpressionStatement':
CseAnimation.handleNode(node.expression);
break;
}
}

static updateAnimation() {
CseAnimation.animationComponents.forEach(a => a.destroy());
CseAnimation.animations.forEach(a => a.destroy());
CseAnimation.clearAnimationComponents();

if (!Layout.previousControlComponent) return;
const lastControlItem = Layout.previousControlComponent.control.peek();
const lastControlComponent = Layout.previousControlComponent.stackItemComponents.at(-1);
const currStashComponent = Layout.stashComponent.stashItemComponents.at(-1);
if (
!CseAnimation.animationEnabled ||
!lastControlItem ||
!lastControlComponent ||
!CseMachine.getControlStash() // TODO: handle cases where there are environment animations
!CseMachine.getControlStash() // TODO: handle cases where there are only environment animations
) {
return;
}
let animation: Animatable | undefined;
if (!isInstr(lastControlItem)) {
switch (lastControlItem.type) {
case 'Literal':
animation = new LiteralAnimation(
lastControlComponent,
Layout.stashComponent.stashItemComponents.at(-1)!
if (isNode(lastControlItem)) {
CseAnimation.handleNode(lastControlItem);
} else {
switch (lastControlItem.instrType) {
case InstrType.APPLICATION:
const appInstr = lastControlItem as AppInstr;
const fnStashItem = Layout.previousStashComponent.stashItemComponents.at(
-appInstr.numOfArgs - 1
)!;
const fn = fnStashItem.value;
if (isBuiltInFn(fn) || isStreamFn(fn)) {
CseAnimation.animations.push(
new InstructionApplicationAnimation(
lastControlComponent,
Layout.previousStashComponent.stashItemComponents.slice(-appInstr.numOfArgs - 1),
currStashComponent!
)
);
break;
}
const frameCreated = appInstr.numOfArgs > 0;

CseAnimation.animations.push(
new FunctionApplicationAnimation(
lastControlComponent,
CseAnimation.getNewControlItems(),
fnStashItem,
Layout.previousStashComponent.stashItemComponents.slice(-appInstr.numOfArgs),
frameCreated ? CseAnimation.currentFrame : undefined
)
);
break;
case 'Program':
case 'ExpressionStatement':
case 'VariableDeclaration':
const currentControlSize = Layout.controlComponent.control.size();
const previousControlSize = Layout.previousControlComponent.control.size();
const numOfItems = currentControlSize - previousControlSize + 1;
if (numOfItems <= 0) break;
const targetItems = Array.from({ length: numOfItems }, (_, i) => {
return Layout.controlComponent.stackItemComponents[previousControlSize + i - 1];
});
animation = new BlockAnimation(lastControlComponent, targetItems);
case InstrType.ARRAY_ACCESS:
CseAnimation.animations.push(
new ArrayAccessAnimation(
lastControlComponent,
Layout.previousStashComponent.stashItemComponents.at(-2)!,
Layout.previousStashComponent.stashItemComponents.at(-1)!,
Layout.stashComponent.stashItemComponents.at(-1)!
)
);
break;
}
} else {
switch (lastControlItem.instrType) {
case InstrType.RESET:
case InstrType.WHILE:
case InstrType.FOR:
case InstrType.ASSIGNMENT:
case InstrType.ARRAY_ASSIGNMENT:
const arrayItem = Layout.previousStashComponent.stashItemComponents.at(-3)!;
CseAnimation.animations.push(
new ArrayAssignmentAnimation(
lastControlComponent,
arrayItem,
Layout.values.get(arrayItem.value.id) as ArrayValue,
Layout.previousStashComponent.stashItemComponents.at(-2)!,
Layout.previousStashComponent.stashItemComponents.at(-1)!,
Layout.stashComponent.stashItemComponents.at(-1)!
)
);
break;
case InstrType.UNARY_OP:
animation = new UnaryOperationAnimation(
lastControlComponent,
Layout.previousStashComponent.stashItemComponents.at(-1)!,
Layout.stashComponent.stashItemComponents.at(-1)!
case InstrType.ARRAY_LITERAL:
const arrSize = (lastControlItem as ArrLitInstr).arity;
CseAnimation.animations.push(
new InstructionApplicationAnimation(
lastControlComponent,
Layout.previousStashComponent.stashItemComponents.slice(-arrSize),
currStashComponent!
)
);
break;
case InstrType.BINARY_OP:
animation = new BinaryOperationAnimation(
lastControlComponent,
Layout.previousStashComponent.stashItemComponents.at(-2)!,
Layout.previousStashComponent.stashItemComponents.at(-1)!,
Layout.stashComponent.stashItemComponents.at(-1)!
case InstrType.ASSIGNMENT:
CseAnimation.animations.push(
new AssignmentAnimation(
lastControlComponent,
currStashComponent!,
...lookupBinding(CseAnimation.currentFrame, (lastControlItem as AssmtInstr).symbol)
)
);
break;
case InstrType.POP:
animation = new PopAnimation(
lastControlComponent,
Layout.previousStashComponent.stashItemComponents.at(-1)!
case InstrType.BINARY_OP:
CseAnimation.animations.push(
new BinaryOperationAnimation(
lastControlComponent,
Layout.previousStashComponent.stashItemComponents.at(-2)!,
Layout.previousStashComponent.stashItemComponents.at(-1)!,
currStashComponent!
)
);
break;
case InstrType.APPLICATION:
case InstrType.BRANCH:
case InstrType.FOR:
case InstrType.WHILE:
CseAnimation.animations.push(
new BranchAnimation(
lastControlComponent,
Layout.previousStashComponent.stashItemComponents.at(-1)!,
CseAnimation.getNewControlItems()
)
);
break;
case InstrType.ENVIRONMENT:
case InstrType.ARRAY_LITERAL:
case InstrType.ARRAY_ACCESS:
case InstrType.ARRAY_ASSIGNMENT:
CseAnimation.animations.push(
new EnvironmentAnimation(CseAnimation.previousFrame, CseAnimation.currentFrame)
);
break;
case InstrType.POP:
const currentStashSize = Layout.stashComponent.stash.size();
const previousStashSize = Layout.previousStashComponent.stash.size();
const lastStashIsUndefined =
currentStashSize === 1 &&
currStashComponent!.text === 'undefined' &&
currentStashSize === previousStashSize;
CseAnimation.animations.push(
new PopAnimation(
lastControlComponent,
Layout.previousStashComponent.stashItemComponents.at(-1)!,
lastStashIsUndefined ? currStashComponent : undefined
)
);
break;
case InstrType.UNARY_OP:
CseAnimation.animations.push(
new UnaryOperationAnimation(
lastControlComponent,
Layout.previousStashComponent.stashItemComponents.at(-1)!,
currStashComponent!
)
);
break;
case InstrType.ARRAY_LENGTH:
case InstrType.CONTINUE_MARKER:
case InstrType.BREAK:
case InstrType.BREAK_MARKER:
case InstrType.CONTINUE_MARKER:
case InstrType.MARKER:
case InstrType.RESET:
break;
}
}
if (animation) CseAnimation.animationComponents.push(animation);
}

static playAnimation(): void {
static async playAnimation() {
if (!CseAnimation.animationEnabled) {
CseAnimation.disableAnimations();
CseAnimation.animations.forEach(a => a.destroy());
CseAnimation.clearAnimationComponents();
return;
}
CseAnimation.disableAnimations();
for (const animationComponent of this.animationComponents) {
animationComponent.animate();
}
// Get the actual HTML <canvas> element and set the pointer events to none, to allow for
// mouse events to pass through the animation layer, and be handled by the actual CSE Machine.
// Setting the listening property to false on the Konva Layer does not seem to work, so
// this a workaround.
const canvasElement = CseAnimation.getLayer()?.getCanvas()._canvas;
if (canvasElement) canvasElement.style.pointerEvents = 'none';
// Play all the animations
await Promise.all(this.animations.map(a => a.animate()));
}
}
Loading