Skip to content

Commit c113a0b

Browse files
committed
Fix some broken things
1 parent bfca65c commit c113a0b

File tree

4 files changed

+124
-11
lines changed

4 files changed

+124
-11
lines changed

lib/lintplugin/src/rules/tabType.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const tabType = {
2222
useHelper: 'Use the defineTab helper from {{ source }}'
2323
},
2424
defaultOptions: [
25-
'@sourceacademy/modules-lib/tabs/utils',
25+
'@sourceacademy/modules-lib/tabs',
2626
'defineTab'
2727
],
2828
},

src/tabs/Curve/src/canvas_3d_curve.tsx

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,120 @@
1-
import { Slider } from '@blueprintjs/core';
1+
import { EditableText, Slider } from '@blueprintjs/core';
22
import type { CurveDrawn } from '@sourceacademy/bundle-curve/curves_webgl';
33
import PlayButton from '@sourceacademy/modules-lib/tabs/PlayButton';
44
import WebGLCanvas from '@sourceacademy/modules-lib/tabs/WebGLCanvas';
55
import { BP_TAB_BUTTON_MARGIN, BP_TEXT_MARGIN, CANVAS_MAX_WIDTH, } from '@sourceacademy/modules-lib/tabs/css_constants';
6+
import { useAnimation } from '@sourceacademy/modules-lib/tabs/useAnimation';
67
import { degreesToRadians } from '@sourceacademy/modules-lib/utilities';
8+
import { clamp } from 'lodash';
79
import React from 'react';
810

11+
export default function Canvas3DCurve({ curve }: Props) {
12+
const canvasRef = React.useRef<HTMLCanvasElement | null>(null);
13+
const [angleText, setAngleText] = React.useState<string | null>(null);
14+
const [isEditing, setIsEditing] = React.useState(false);
15+
16+
const {
17+
isPlaying: isRotating,
18+
start,
19+
stop,
20+
changeTimestamp: setDisplayAngle,
21+
timestamp: displayAngle,
22+
setCanvas,
23+
} = useAnimation({
24+
animationDuration: 7200,
25+
autoLoop: true,
26+
callback(angle) {
27+
const angleInRadians = degreesToRadians(angle / 20);
28+
curve.redraw(angleInRadians);
29+
}
30+
});
31+
32+
React.useEffect(() => {
33+
if (canvasRef.current) {
34+
curve.init(canvasRef.current);
35+
setCanvas(canvasRef.current);
36+
}
37+
}, [curve, canvasRef.current]);
38+
39+
return <div
40+
style={{ width: '100%' }}
41+
>
42+
<div
43+
style={{
44+
display: 'flex',
45+
justifyContent: 'center'
46+
}}
47+
>
48+
<div
49+
style={{
50+
display: 'flex',
51+
alignItems: 'center',
52+
gap: BP_TAB_BUTTON_MARGIN,
53+
54+
width: '100%',
55+
maxWidth: CANVAS_MAX_WIDTH,
56+
57+
paddingTop: BP_TEXT_MARGIN,
58+
paddingBottom: BP_TEXT_MARGIN
59+
}}
60+
>
61+
<PlayButton
62+
isPlaying={isRotating}
63+
onClick={() => {
64+
if (isRotating) stop();
65+
else start();
66+
}}
67+
/>
68+
<Slider
69+
value={displayAngle / 20}
70+
min={0}
71+
max={360}
72+
labelRenderer={false}
73+
onChange={newValue => {
74+
stop();
75+
setDisplayAngle(newValue * 20);
76+
}}
77+
/>
78+
<EditableText
79+
customInputAttributes={{
80+
style: { height: '100%' }
81+
}}
82+
isEditing={isEditing}
83+
onEdit={() => setIsEditing(true)}
84+
type="number"
85+
value={angleText ?? Math.round(displayAngle / 20).toString()}
86+
disabled={isRotating}
87+
onChange={value => {
88+
setAngleText(value);
89+
if (isEditing) return;
90+
91+
const angle = parseFloat(value);
92+
if (!Number.isNaN(angle)) {
93+
setDisplayAngle(clamp(angle, 0, 360) * 20);
94+
}
95+
setAngleText(null);
96+
}}
97+
onConfirm={value => {
98+
const angle = parseFloat(value);
99+
setDisplayAngle(clamp(angle, 0, 360) * 20);
100+
setAngleText(null);
101+
setIsEditing(false);
102+
}}
103+
onCancel={() => setIsEditing(false)}
104+
/>
105+
</div>
106+
</div>
107+
<div
108+
style={{
109+
display: 'flex',
110+
justifyContent: 'center'
111+
}}
112+
>
113+
<WebGLCanvas ref={canvasRef} />
114+
</div>
115+
</div>;
116+
}
117+
9118
type State = {
10119
/**
11120
* Slider component reflects this value. This value is also passed in as
@@ -31,7 +140,7 @@ type Props = {
31140
*
32141
* Uses WebGLCanvas internally.
33142
*/
34-
export default class Canvas3dCurve extends React.Component<Props, State> {
143+
export class Canvas3dCurve extends React.Component<Props, State> {
35144
private canvas: HTMLCanvasElement | null;
36145

37146
constructor(props) {

src/tabs/Curve/src/curve_3d_animation_canvas.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default function Curve3DAnimationCanvas({ animation }: Props) {
2424

2525
const frameDuration = 1000 / animation.fps;
2626
const animationDuration = Math.round(animation.duration * 1000);
27-
const { changeTimestamp, drawFrame, start, stop, reset, timestamp, isPlaying, canvasRef } = useAnimation({
27+
const { changeTimestamp, drawFrame, start, stop, reset, timestamp, isPlaying, setCanvas } = useAnimation({
2828
frameDuration, animationDuration, autoLoop: isAutoLooping,
2929
callback(timestamp, canvas) {
3030
try {
@@ -178,7 +178,11 @@ export default function Curve3DAnimationCanvas({ animation }: Props) {
178178
style={{
179179
flexGrow: 1
180180
}}
181-
ref={canvasRef}
181+
ref={canvas => {
182+
if (canvas) {
183+
setCanvas(canvas);
184+
}
185+
}}
182186
/>
183187
)}
184188
</div>

src/tabs/Rune/src/hollusion_canvas.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export default function HollusionCanvas({ rune }: Props) {
1515
// to reinitialize the shaders every time
1616
const renderFuncRef = React.useRef<(time: number) => void>();
1717

18-
const { start, canvasRef } = useAnimation({
18+
const { setCanvas } = useAnimation({
1919
callback(timestamp, canvas) {
2020
if (renderFuncRef.current === undefined) {
2121
renderFuncRef.current = rune.draw(canvas);
@@ -25,9 +25,9 @@ export default function HollusionCanvas({ rune }: Props) {
2525
autoStart: true
2626
});
2727

28-
React.useEffect(() => {
29-
start();
30-
}, [rune]);
31-
32-
return <WebGLCanvas ref={canvasRef} />;
28+
return <WebGLCanvas ref={canvas => {
29+
if (canvas) {
30+
setCanvas(canvas);
31+
}
32+
}} />;
3333
}

0 commit comments

Comments
 (0)