Skip to content
This repository has been archived by the owner on Sep 8, 2024. It is now read-only.

Commit

Permalink
feat: setup
Browse files Browse the repository at this point in the history
  • Loading branch information
sheepbox8646 committed Apr 27, 2024
1 parent d29c2f0 commit 7e6eca0
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 24 deletions.
28 changes: 14 additions & 14 deletions mods/mod-math/src/widgets/tex.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { AsyncWidgetResponse, WidgetOptions } from '@newcar/core'
import { AsyncWidget } from '@newcar/core'
import type { Canvas, CanvasKit, Paint, Path } from 'canvaskit-wasm'
import { mathjax } from 'mathjax-full/js/mathjax.js'
import { TeX } from 'mathjax-full/js/input/tex.js'
import { SVG } from 'mathjax-full/js/output/svg.js'
import { liteAdaptor } from 'mathjax-full/js/adaptors/liteAdaptor.js'
import { RegisterHTMLHandler } from 'mathjax-full/js/handlers/html.js'
import { mathjax } from 'mathjax-full/js/mathjax.js';
import { TeX } from 'mathjax-full/js/input/tex.js';
import { SVG } from 'mathjax-full/js/output/svg.js';
import { liteAdaptor } from 'mathjax-full/js/adaptors/liteAdaptor.js';
import { RegisterHTMLHandler } from 'mathjax-full/js/handlers/html.js';
import { svg2path } from '../utils/svg2path'

export class Tex extends AsyncWidget {
Expand All @@ -23,24 +23,24 @@ export class Tex extends AsyncWidget {
this.paint.setColor(ck.WHITE)
this.paint.setStrokeWidth(2)

const adaptor = liteAdaptor()
RegisterHTMLHandler(adaptor)
const adaptor = liteAdaptor();
RegisterHTMLHandler(adaptor);

const tex = new TeX({ packages: ['base', 'autoload', 'require', 'ams'] })
const svg = new SVG({ fontCache: 'none' })
const doc = mathjax.document('', { InputJax: tex, OutputJax: svg })
const tex = new TeX({ packages: ['base', 'autoload', 'require', 'ams'] });
const svg = new SVG({ fontCache: 'none' });
const doc = mathjax.document('', { InputJax: tex, OutputJax: svg });

this.convertTexToSVG = (texString: string) => {
const node = doc.convert(texString, {
display: true,
})
return adaptor.outerHTML(node)
display: true
});
return adaptor.outerHTML(node);
}
for (const path of svg2path(this.convertTexToSVG(this.tex)))
this.path.addPath(ck.Path.MakeFromSVGString(path.path)!)

return {
status: 'ok',
status: 'ok'
}
}

Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/apiWait.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function wait(value: number, unit?: 'frame' | 'second') {
return {
duration: value,
unit,
remaining: value,
}
}
4 changes: 4 additions & 0 deletions packages/core/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export class App {
// Animating.
app.scene.root.runAnimation(app.scene.elapsed)

// Process setup generation function
app.scene.root.runSetup(app.scene.elapsed)


for (const plugin of app.plugins) plugin.afterUpdate(app, app.scene.elapsed)

if (app.playing) {
Expand Down
64 changes: 54 additions & 10 deletions packages/core/src/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { AnimationTree } from './animationTree'
import { analyseAnimationTree } from './animationTree'
import type { Event, EventInstance } from './event'
import type { BlendMode } from './utils/types'
import type { wait } from './apiWait'

export type WidgetInstance<T extends Widget> = T

Expand Down Expand Up @@ -44,6 +45,7 @@ export class Widget {
animationInstances: AnimationInstance[] = []
eventInstances: EventInstance[] = []
updates: ((elapsed: number, widget: Widget) => void)[] = []
setups: GeneratorFunction[] = []
key = `widget-${0}-${performance.now()}-${Math.random()
.toString(16)
.slice(2)}`
Expand Down Expand Up @@ -78,7 +80,7 @@ export class Widget {
* Called when the widget is registered.
* @param _ck The CanvasKit namespace
*/
init(_ck: CanvasKit) {}
init(_ck: CanvasKit) { }

/**
* Preload the necessary items during drawing.
Expand All @@ -88,14 +90,14 @@ export class Widget {
* @param propertyChanged The changed property of this widget
*/

predraw(_ck: CanvasKit, _propertyChanged: string) {}
predraw(_ck: CanvasKit, _propertyChanged: string) { }

/**
* Draw the object according to the parameters of the widget.
* Called when the parameters is changed.
* @param _canvas The canvas object of CanvasKit-WASM.
*/
draw(_canvas: Canvas) {}
draw(_canvas: Canvas) { }

/**
* Called when the parameters is changed.
Expand All @@ -114,7 +116,8 @@ export class Widget {
canvas.translate(this.x, this.y)
canvas.rotate(this.style.rotation, this.centerX, this.centerY)
canvas.scale(this.style.scaleX, this.style.scaleY)
if (this.display) this.draw(canvas)
if (this.display)
this.draw(canvas)
}

/**
Expand Down Expand Up @@ -168,8 +171,8 @@ export class Widget {
runAnimation(elapsed: number) {
for (const instance of this.animationInstances) {
if (
instance.startAt <= elapsed &&
instance.during + instance.startAt >= elapsed
instance.startAt <= elapsed
&& instance.during + instance.startAt >= elapsed
) {
if (instance.mode === 'positive') {
instance.animation.act(
Expand All @@ -178,7 +181,8 @@ export class Widget {
(elapsed - instance.startAt) / instance.during,
instance.params,
)
} else if (instance.mode === 'reverse') {
}
else if (instance.mode === 'reverse') {
instance.animation.act(
this,
elapsed - instance.startAt,
Expand All @@ -201,6 +205,46 @@ export class Widget {
for (const child of this.children) child.setEventListener(element)
}

async runSetup(elapsed: number) {
for (const setupFunc of this.setups) {
const generator = setupFunc(this, (animation: Animation<any>, duration: number, params: Record<string, any>) => {
this.animationInstances.push({
startAt: elapsed,
during: duration,
animation,
params,
mode: params.mode ?? 'positive',
})
})

let result = generator.next()
while (!result.done) {
const waitInstruction = result.value
if (waitInstruction && waitInstruction.duration)
await this.handleWait(waitInstruction)

result = generator.next()
}
}
for (const child of this.children)
child.runSetup(elapsed)
}

async handleWait(waitInstruction: ReturnType<typeof wait>) {
const { duration, unit } = waitInstruction
if (unit === 'second') {
await new Promise(resolve => setTimeout(resolve, duration * 1000))
}
else if (unit === 'frame') {
// 假设帧率为 60 fps
await new Promise(resolve => setTimeout(resolve, (duration / 60) * 1000))
}
}

setup(call: GeneratorFunction) {
this.setups.push(call)
}

/**
* Set up a update function to call it when the widget is changed.
* @param updateFunc The frame from having gone to current frame.
Expand Down Expand Up @@ -234,12 +278,12 @@ export class Widget {
return false
}

static getAbsoluteCoordinates(widget: Widget): { x: number; y: number } {
static getAbsoluteCoordinates(widget: Widget): { x: number, y: number } {
function getCoordinates(
widget: Widget,
x: number,
y: number,
): { x: number; y: number } {
): { x: number, y: number } {
let parent = widget.parent
let absoluteX = x
let absoluteY = y
Expand All @@ -260,7 +304,7 @@ export class Widget {
widget: Widget,
x: number,
y: number,
): { x: number; y: number } {
): { x: number, y: number } {
const { x: absoluteX, y: absoluteY } = Widget.getAbsoluteCoordinates(widget)
const relativeX = x - absoluteX
const relativeY = y - absoluteY
Expand Down

0 comments on commit 7e6eca0

Please sign in to comment.