diff --git a/cli/src/build/index.ts b/cli/src/build/index.ts index 71116451e..c0d049931 100644 --- a/cli/src/build/index.ts +++ b/cli/src/build/index.ts @@ -36,27 +36,34 @@ async function resolveApp(path: string): Promise { return app.default } -async function exportFile(path: string, files: string[], fps: number) { - for (let i = 0; i < files.length; i++) { - await new Promise((resolve, reject) => { - ffmpeg() - .on('error', (err: Error) => { - console.error(`An error occurred: ${err.message}`) - reject(err) - }) - .input(files[i]) - .inputFPS(fps) - .output(path) - .outputFPS(30) - .addInput(resolve(`./temp_image_${i}.png`)) - .addOption('-vf', `fps=${fps}`) - .on('end', () => { - console.log(`Frame ${i + 1} processed.`) - fs.unlinkSync(files[i]) - resolve(null) - }) - .run() - }) +async function exportFile(outputPath: string, inputFiles: string[], fps: number) { + // Create an array to store the promises returned by the FFmpeg process + const promises = [] + + // Iterate over the input files and push the FFmpeg promises to the array + for (let i = 0; i < inputFiles.length; i++) { + promises.push( + new Promise((resolve, reject) => { + ffmpeg(inputFiles[i]) + .on('error', (err: Error) => { + console.error(`An error occurred: ${err.message}`) + reject(err) + }) + .inputFPS(fps) + .output(outputPath) // Use the outputPath here + .outputFPS(fps) + .on('end', () => { + console.log(`Frame ${i + 1} processed.`) + fs.unlinkSync(inputFiles[i]) // Remove the original file + resolve(null) + }) + .run() + }), + ) } + + // Wait for all FFmpeg processes to finish + await Promise.all(promises) + console.log('Processing finished!') } diff --git a/cli/src/test/main.mjs b/cli/src/test/main.mjs index 23e82cfea..399540fa0 100644 --- a/cli/src/test/main.mjs +++ b/cli/src/test/main.mjs @@ -1,26 +1,17 @@ -import { CarEngine, ImageWidget, Scene, Text, Widget, move, useFont, useImage } from 'newcar' +import { CarEngine, ImageWidget, Scene, Widget, move, useImage } from 'newcar' const logoLoaded = await useImage('./assets/newcar.webp') -await useFont('./fonts/bahnschrift.ttf') const engine = await new CarEngine().init('../../node_modules/canvaskit-wasm/bin/canvaskit.wasm') const app = engine.createLocalApp(700, 700) +app.config.unit = 'frame' const logo = new ImageWidget(logoLoaded, { style: { scaleX: 0.4, scaleY: 0.4, }, -}) -const text = new Text(['Hello Newcar!'], { - y: 600, - style: { - textAlign: 'center', - }, -}).animate(move, 0, 300, { - from: [0, 600], - to: [-1400, 600], -}) -const root = new Widget().add(text, logo) +}).animate(move().withAttr({ duration: 1, to: [400, 400] })) +const root = new Widget().add(logo) const scene = new Scene(root) app.checkout(scene) diff --git a/examples/main.ts b/examples/main.ts index 90580704f..4e630e65e 100644 --- a/examples/main.ts +++ b/examples/main.ts @@ -2,7 +2,7 @@ import * as nc from 'newcar' import scene1 from './scene1' import timeview from '@newcar/plugin-timeview' -const milestone = document.querySelector('#milestone') as HTMLCanvasElement +// const milestone = document.querySelector('#milestone') as HTMLCanvasElement // window.addEventListener('resize', () => { // milestone.width = window.innerWidth // milestone.height = window.innerHeight @@ -10,9 +10,11 @@ const milestone = document.querySelector('#milestone') as HTMLCanvasElement // window.dispatchEvent(new Event('resize')) const engine = await new nc.CarEngine().init('./node_modules/canvaskit-wasm/bin/canvaskit.wasm') -const app = engine.createApp(milestone) +const app = engine.createApp(document.querySelector('#milestone')) app.checkout(scene1) -app.play() \ No newline at end of file +app.play() + +export default app \ No newline at end of file diff --git a/examples/scene1.ts b/examples/scene1.ts index feac05e1c..53edc2cf7 100644 --- a/examples/scene1.ts +++ b/examples/scene1.ts @@ -159,8 +159,8 @@ import * as gm from '@newcar/mod-geometry' await nc.useFont('./Roboto-Regular.ttf') export default nc.createScene( - new mt.PolarPlane(200, { + new mt.NumberAxis([-500, 500], { x: 300, - y: 300 - }).animate(nc.create().withAttr({ duration: 1 })) + y: 200 + }) ) \ No newline at end of file diff --git a/mods/mod-math/src/widgets/numberAxis.ts b/mods/mod-math/src/widgets/numberAxis.ts index a52d6cfee..f5fb30606 100644 --- a/mods/mod-math/src/widgets/numberAxis.ts +++ b/mods/mod-math/src/widgets/numberAxis.ts @@ -1,5 +1,5 @@ import { Arrow, Line, Text } from '@newcar/basic' -import type { ConvertToProp, Reactive, WidgetOptions, WidgetStyle } from '@newcar/core' +import type { ConvertToProp, Reactive, Ref, WidgetOptions, WidgetStyle } from '@newcar/core' import { Widget, changed, reactive, ref } from '@newcar/core' import { Color } from '@newcar/utils' import type { CanvasKit } from 'canvaskit-wasm' @@ -42,8 +42,8 @@ export interface NumberAxisStyle extends WidgetStyle { } export class NumberAxis extends Widget { - division: number - trend: Trend + division: Ref + trend: Ref declare style: ConvertToProp ticks: Line[] texts: Text[] @@ -57,8 +57,8 @@ export class NumberAxis extends Widget { options ??= {} super(options) this.length = reactive(length) - this.division = options.division ?? 50 - this.trend = options.trend ?? (x => x / 50) + this.division = ref(options.division ?? 50) + this.trend = ref(options.trend ?? (x => x / 50)) this.style ??= {} this.style.ticks = ref(options.style.ticks ?? true) this.style.tickColor = reactive(options.style.tickColor ?? Color.WHITE) @@ -74,7 +74,7 @@ export class NumberAxis extends Widget { }) this.ticks = [] this.texts = [] - for (let x = this.length[0] + (this.length[1] - this.length[0]) % this.division; x <= this.length[1]; x += this.division) { + for (let x = this.length[0] + (this.length[1] - this.length[0]) % this.division.value; x <= this.length[1]; x += this.division.value) { if (this.style.ticks) { this.ticks.push( new Line([x, -5], [x, 5], { @@ -86,7 +86,7 @@ export class NumberAxis extends Widget { ) } if (this.style.texts) { - this.texts.push(new Text(this.trend(x).toString(), { + this.texts.push(new Text(this.trend.value(x).toString(), { x: x - (this.style.textSize.value / 2), y: 10, style: { @@ -126,7 +126,7 @@ export class NumberAxis extends Widget { }) changed(this.style.ticks, (v) => { if (v.value) { - for (let x = this.length[0] + (this.length[1] - this.length[0]) % this.division; x <= this.length[1]; x += this.division) { + for (let x = this.length[0] + (this.length[1] - this.length[0]) % this.division.value; x <= this.length[1]; x += this.division.value) { this.ticks.push( new Line([x, -5], [x, 5], { style: { @@ -144,8 +144,8 @@ export class NumberAxis extends Widget { }) changed(this.style.texts, (v) => { if (v.value) { - for (let x = this.length[0] + (this.length[1] - this.length[0]) % this.division; x <= this.length[1]; x += this.division) { - this.texts.push(new Text(this.trend(x).toString(), { + for (let x = this.length[0] + (this.length[1] - this.length[0]) % this.division.value; x <= this.length[1]; x += this.division.value) { + this.texts.push(new Text(this.trend.value(x).toString(), { x: x - (this.style.textSize.value / 2), y: 10, style: { @@ -166,9 +166,9 @@ export class NumberAxis extends Widget { function reset(this: NumberAxis) { this.texts = [] this.ticks = [] - for (let x = this.length[0] + (this.length[1] - this.length[0]) % this.division; x <= this.length[1]; x += this.division) { + for (let x = this.length[0] + (this.length[1] - this.length[0]) % this.division.value; x <= this.length[1]; x += this.division.value) { if (this.style.texts) { - this.texts.push(new Text(this.trend(x).toString(), { + this.texts.push(new Text(this.trend.value(x).toString(), { x: x - (this.style.textSize.value / 2), y: 10, style: { diff --git a/packages/core/src/localApp.ts b/packages/core/src/localApp.ts index fc921f0d5..732bf4433 100644 --- a/packages/core/src/localApp.ts +++ b/packages/core/src/localApp.ts @@ -10,8 +10,6 @@ import { type Config, defineConfig } from './config' export class LocalApp { scene: Scene surface: Surface - private playing = false - private last: Widget updates: ((elapsed: number) => void)[] = [] canvas: Canvas config: Config @@ -46,16 +44,12 @@ export class LocalApp { for (const plugin of this.plugins) plugin.beforeCheckout(this, scene) this.scene = scene - this.last = this.scene.root for (const plugin of this.plugins) plugin.onCheckout(this, this.scene) return this } static update(app: LocalApp): void { - if (!app.playing) - return - for (const plugin of app.plugins) { if (plugin.beforeUpdate) plugin.beforeUpdate(app, app.scene.elapsed) diff --git a/packages/core/src/prop.ts b/packages/core/src/prop.ts index 765bad34d..47ef440ff 100644 --- a/packages/core/src/prop.ts +++ b/packages/core/src/prop.ts @@ -9,10 +9,12 @@ export type Listener = (newValue: Reactive) => void export const REACTIVE_TAG = Symbol('reactive') function _reactive(value: T, listener?: Listener, reactType: number = 1) { - if (typeof value !== 'object') - return if (value === undefined) return + if (typeof value !== 'object') + return + if (REACTIVE_TAG in (value as any)) + return value const postListeners: Listener[] = listener ? [listener] : [] const preListeners: Listener[] = [] diff --git a/packages/core/src/scene.ts b/packages/core/src/scene.ts index 4e0bb4a97..61e2827af 100644 --- a/packages/core/src/scene.ts +++ b/packages/core/src/scene.ts @@ -19,6 +19,6 @@ export class Scene { } } -export function createScene(root: Widget) { +export function createScene(root: T) { return new Scene(root) } diff --git a/packages/core/src/widget.ts b/packages/core/src/widget.ts index 512938f7c..34e2f4eee 100644 --- a/packages/core/src/widget.ts +++ b/packages/core/src/widget.ts @@ -39,7 +39,7 @@ export interface WidgetStyle { margin?: [number, number, number, number] | [number, number] | number } -export class Widget { +export abstract class Widget { plugins: WidgetPlugin[] = [] pos: Ref x: Ref // The vector x of the widget. @@ -170,7 +170,7 @@ export class Widget { * Add children widgets for the widget. * @param children The added children. */ - add(...children: Widget[] | ((parent: Widget) => Widget)[]): this { + add(...children: (Widget | ((parent: Widget) => Widget))[]): this { // let index = 0 for (let child of children) { if (typeof child === 'function') @@ -257,8 +257,8 @@ export class Widget { return this } - setup(setupFunc: SetupFunction): this { - const generator = setupFunc(this as T) + setup(setupFunc: SetupFunction): this { + const generator = setupFunc(this) this.setups.push({ generator: generator as any, nextFrame: 0 }) return this }