diff --git a/packages/core/src/animation/Keyframe.ts b/packages/core/src/animation/Keyframe.ts index 1a52f721c4..b4a50c80ee 100644 --- a/packages/core/src/animation/Keyframe.ts +++ b/packages/core/src/animation/Keyframe.ts @@ -10,16 +10,16 @@ export class Keyframe< T = V extends number ? number : V extends Vector2 - ? Vector2 - : V extends Vector3 - ? Vector3 - : V extends Vector4 | Color | Quaternion | Rect - ? Vector4 - : V extends number[] | Float32Array - ? number[] - : V extends ReferResource - ? ReferResource - : never + ? Vector2 + : V extends Vector3 + ? Vector3 + : V extends Vector4 | Color | Quaternion | Rect + ? Vector4 + : V extends number[] | Float32Array + ? number[] + : V extends ReferResource + ? ReferResource + : never > { /** The time of the Keyframe. */ time: number; diff --git a/packages/core/src/animation/internal/animationCurveOwner/AnimationCurveOwner.ts b/packages/core/src/animation/internal/animationCurveOwner/AnimationCurveOwner.ts index 4bd51e0424..6406f380e6 100644 --- a/packages/core/src/animation/internal/animationCurveOwner/AnimationCurveOwner.ts +++ b/packages/core/src/animation/internal/animationCurveOwner/AnimationCurveOwner.ts @@ -92,8 +92,8 @@ export class AnimationCurveOwner { ? srcCurve._evaluateAdditive(srcTime, this.baseEvaluateData) : srcCurve._evaluate(srcTime, this.baseEvaluateData) : additive - ? this.cureType._getZeroValue(this.baseEvaluateData.value) - : this.defaultValue; + ? this.cureType._getZeroValue(this.baseEvaluateData.value) + : this.defaultValue; const destValue = destCurve && destCurve.keys.length @@ -101,8 +101,8 @@ export class AnimationCurveOwner { ? destCurve._evaluateAdditive(destTime, this.crossEvaluateData) : destCurve._evaluate(destTime, this.crossEvaluateData) : additive - ? this.cureType._getZeroValue(this.crossEvaluateData.value) - : this.defaultValue; + ? this.cureType._getZeroValue(this.crossEvaluateData.value) + : this.defaultValue; return this._lerpValue(srcValue, destValue, crossWeight); } @@ -126,8 +126,8 @@ export class AnimationCurveOwner { ? destCurve._evaluateAdditive(destTime, this.crossEvaluateData) : destCurve._evaluate(destTime, this.crossEvaluateData) : additive - ? this.cureType._getZeroValue(this.crossEvaluateData.value) - : this.defaultValue; + ? this.cureType._getZeroValue(this.crossEvaluateData.value) + : this.defaultValue; return this._lerpValue(srcValue, destValue, crossWeight); } diff --git a/packages/core/src/asset/AssetType.ts b/packages/core/src/asset/AssetType.ts index e5d6fef91f..ecc650ead7 100644 --- a/packages/core/src/asset/AssetType.ts +++ b/packages/core/src/asset/AssetType.ts @@ -56,5 +56,7 @@ export enum AssetType { /** Source Font, include ttf、 otf and woff. */ SourceFont = "SourceFont", /** Project asset. */ - Project = "project" + Project = "project", + /** Script in ES module. */ + Script = "Script" } diff --git a/packages/loader/src/ScriptLoader.ts b/packages/loader/src/ScriptLoader.ts new file mode 100644 index 0000000000..791f067eed --- /dev/null +++ b/packages/loader/src/ScriptLoader.ts @@ -0,0 +1,24 @@ +import { AssetPromise, AssetType, Loader, LoadItem, resourceLoader } from "@galacean/engine-core"; + +@resourceLoader(AssetType.Script, ["js", "mjs"], false) +export class ScriptLoader extends Loader { + load(item: LoadItem): AssetPromise { + return new AssetPromise((resolve, reject) => { + (import(/* @vite-ignore */ item.url) as Promise) + .then((esModule) => { + resolve(esModule); + }) + .catch(reject); + }); + } +} + +/** + * Represents a generic ES module that can have a default export and additional named exports. + */ +export interface ESModule { + /** Default export of the module. */ + default?: any; + /** Named exports from the module. */ + [key: string]: any; +} diff --git a/packages/loader/src/index.ts b/packages/loader/src/index.ts index b1da2b95ee..4b08f3c12f 100644 --- a/packages/loader/src/index.ts +++ b/packages/loader/src/index.ts @@ -19,12 +19,14 @@ import "./SpriteLoader"; import "./Texture2DLoader"; import "./TextureCubeLoader"; import "./ktx2/KTX2Loader"; +import "./ScriptLoader"; export { GLTFLoader } from "./GLTFLoader"; export type { GLTFParams } from "./GLTFLoader"; export * from "./SceneLoader"; export type { Texture2DParams } from "./Texture2DLoader"; export { parseSingleKTX } from "./compressed-texture"; +export { ScriptLoader, type ESModule } from "./ScriptLoader"; export * from "./gltf"; export { KTX2Loader, KTX2Transcoder } from "./ktx2/KTX2Loader"; export { KTX2TargetFormat } from "./ktx2/KTX2TargetFormat"; diff --git a/rollup.config.js b/rollup.config.js index f616b01aec..71fee30596 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -202,4 +202,4 @@ function getAll() { return [...getModule(), ...getMini(), ...getUMD()]; } -export default Promise.all(promises); +export default Promise.all(promises); \ No newline at end of file diff --git a/tests/src/loader/ScriptLoader.test.ts b/tests/src/loader/ScriptLoader.test.ts new file mode 100644 index 0000000000..de8aa8a8d8 --- /dev/null +++ b/tests/src/loader/ScriptLoader.test.ts @@ -0,0 +1,58 @@ +import { WebGLEngine } from "@galacean/engine-rhi-webgl"; +import { AssetType } from "@galacean/engine-core"; +import "@galacean/engine-loader"; +import { ESModule } from "@galacean/engine-loader"; +import { describe, it, expect, beforeAll, afterAll } from "vitest"; + +let engine: WebGLEngine; + +beforeAll(async () => { + const canvasDOM = document.createElement("canvas"); + canvasDOM.width = 1024; + canvasDOM.height = 1024; + engine = await WebGLEngine.create({ canvas: canvasDOM }); +}); + +describe("ScriptLoader test", function () { + it("loader from string url", async () => { + + engine.resourceManager.load({ + url: "https://cdn.jsdelivr.net/npm/colord@2.9.3/+esm", + type: AssetType.Script + }) + .then((script) => { + expect(script).not.to.be.null; + expect(script.default).not.to.be.null; + expect(script.colord).not.to.be.null; + expect(script.getFormat).not.to.be.null; + expect(script.random).not.to.be.null; + }); + }); + + it("loader from blob raw script text", async () => { + const esModuleString = ` + import { Script } from 'https://galaceancdn.com/@galacean/engine@1.3.15'; + export class TestScript extends Script {} + export const colord = "colord"; + export const getFormat = () => "getFormat"; + export default colord; + ` + engine.resourceManager.load({ + url: URL.createObjectURL(new Blob([esModuleString], { type: "application/javascript" })), + type: AssetType.Script + }) + .then((script) => { + expect(script).not.to.be.null; + expect(script.colord).not.to.be.null; + expect(script.getFormat).not.to.be.null; + expect(script.TestScript).not.to.be.null; + expect(script.default).not.to.be.null; + expect(script.default).equal(script.colord) + }) + }); + + afterAll(function () { + engine.resourceManager.gc(); + engine.destroy(); + }); +});