diff --git a/e2e/case/project-loader.ts b/e2e/case/project-loader.ts index d23a4424c9..256fca016d 100644 --- a/e2e/case/project-loader.ts +++ b/e2e/case/project-loader.ts @@ -17,7 +17,7 @@ WebGLEngine.create({ canvas: "canvas", shaderLab }).then((engine) => { engine.resourceManager .load({ type: AssetType.Project, - url: "https://mdn.alipayobjects.com/oasis_be/afts/file/A*fe1xS4Anh3AAAAAAQPAAAAgAekp5AQ/project.json" + url: "https://mdn.alipayobjects.com/oasis_be/afts/file/A*qGzdR5VaZToAAAAAQJAAAAgAekp5AQ/project.json" }) .then(() => { const cameraEntity = engine.sceneManager.activeScene.findEntityByName("Camera"); diff --git a/packages/core/src/asset/ResourceManager.ts b/packages/core/src/asset/ResourceManager.ts index c2fc4b9ebd..0395b2b29b 100644 --- a/packages/core/src/asset/ResourceManager.ts +++ b/packages/core/src/asset/ResourceManager.ts @@ -570,38 +570,33 @@ export class ResourceManager { /** @internal */ _objectPool: { [key: string]: any } = Object.create(null); /** @internal */ - _idResourceMap: Record = Object.create(null); - /** @internal */ _virtualPathResourceMap: Record = Object.create(null); /** * @internal * @beta Just for internal editor, not recommended for developers. */ - getResourceByRef(ref: { refId: string; key?: string; isClone?: boolean }): AssetPromise { - const { refId, key, isClone } = ref; - const obj = this._objectPool[refId]; - let promise: AssetPromise; - if (obj) { - promise = AssetPromise.resolve(obj); - } else { - const resourceConfig = this._idResourceMap[refId]; - if (!resourceConfig) { - Logger.warn(`refId:${refId} is not find in this._idResourceMap.`); - return AssetPromise.resolve(null); - } - let url = resourceConfig.virtualPath; - if (key) { - url += "?q=" + key; - } + getResourceByRef(ref: { url: string; key?: string; isClone?: boolean }): AssetPromise { + const { url, key, isClone } = ref; + if (!url) { + Logger.warn("ResourceManager.getResourceByRef: url is empty."); + return AssetPromise.resolve(null); + } - promise = this.load({ - url, - type: resourceConfig.type, - params: resourceConfig.params - }); + const cached = this._objectPool[url]; + if (cached) { + return AssetPromise.resolve(isClone ? ((cached)).clone() : cached); } - return promise.then((item) => (isClone ? ((item)).clone() : item)); + + const mapped = this._virtualPathResourceMap[url]; + if (!mapped) { + Logger.warn(`ResourceManager.getResourceByRef: url "${url}" not found in virtualPathResourceMap.`); + return AssetPromise.resolve(null); + } + + const loadUrl = key ? url + "?q=" + key : url; + const promise = this.load({ url: loadUrl, type: mapped.type, params: mapped.params }); + return isClone ? promise.then((item) => ((item)).clone()) : promise; } /** @@ -611,7 +606,6 @@ export class ResourceManager { initVirtualResources(config: EditorResourceItem[]): void { config.forEach((element) => { this._virtualPathResourceMap[element.virtualPath] = element; - this._idResourceMap[element.id] = element; if (element.dependentAssetMap) { this._virtualPathResourceMap[element.virtualPath].dependentAssetMap = element.dependentAssetMap; } @@ -653,13 +647,11 @@ const rePropName = RegExp( "g" ); -type ResourceId = string; type VirtualPath = string; type EditorResourceItem = { virtualPath: string; path: string; type: string; - id: string; dependentAssetMap?: { [key: string]: string }; subpackageName?: string; params?: Record; diff --git a/packages/loader/src/AnimationClipLoader.ts b/packages/loader/src/AnimationClipLoader.ts index 58227e65fc..b27872d84c 100644 --- a/packages/loader/src/AnimationClipLoader.ts +++ b/packages/loader/src/AnimationClipLoader.ts @@ -10,7 +10,7 @@ import { } from "@galacean/engine-core"; import { decode } from "./resource-deserialize"; -@resourceLoader(AssetType.AnimationClip, ["ani"]) +@resourceLoader(AssetType.AnimationClip, ["anim"]) class AnimationClipLoader extends Loader { load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { return new AssetPromise((resolve, reject) => { @@ -45,7 +45,7 @@ class AnimationClipLoader extends Loader { private _parseKeyframeValue(keyframe: any, resourceManager: ResourceManager): Promise { const value = keyframe.value; - if (typeof value === "object" && (value as any)?.refId) { + if (typeof value === "object" && (value as any)?.url) { return new Promise((resolve) => { resourceManager // @ts-ignore diff --git a/packages/loader/src/AnimatorControllerLoader.ts b/packages/loader/src/AnimatorControllerLoader.ts index 161d107b7f..b28a89ddb9 100644 --- a/packages/loader/src/AnimatorControllerLoader.ts +++ b/packages/loader/src/AnimatorControllerLoader.ts @@ -14,7 +14,7 @@ import { WrapMode } from "@galacean/engine-core"; -@resourceLoader(AssetType.AnimatorController, ["json"], false) +@resourceLoader(AssetType.AnimatorController, ["animCtrl"]) class AnimatorControllerLoader extends Loader { load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { return new AssetPromise((resolve, reject) => { diff --git a/packages/loader/src/BufferLoader.ts b/packages/loader/src/BufferLoader.ts index f7071ec240..9addae98c6 100644 --- a/packages/loader/src/BufferLoader.ts +++ b/packages/loader/src/BufferLoader.ts @@ -10,7 +10,7 @@ import { const base64Regex = /^data:(.+?);base64,/; -@resourceLoader(AssetType.Buffer, ["bin", "r3bin"]) +@resourceLoader(AssetType.Buffer, ["bin"]) class BufferLoader extends Loader { load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { const { url } = item; diff --git a/packages/loader/src/MaterialLoader.ts b/packages/loader/src/MaterialLoader.ts index 162d2e0c87..ec3c2a9942 100644 --- a/packages/loader/src/MaterialLoader.ts +++ b/packages/loader/src/MaterialLoader.ts @@ -31,7 +31,7 @@ function parseProperty(object: Object, key: string, value: any) { } } -@resourceLoader(AssetType.Material, ["json"]) +@resourceLoader(AssetType.Material, ["mat"]) class MaterialLoader extends Loader { load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { return new AssetPromise((resolve, reject) => { diff --git a/packages/loader/src/PhysicsMaterialLoader.ts b/packages/loader/src/PhysicsMaterialLoader.ts index 334e60a618..d30bb619d0 100644 --- a/packages/loader/src/PhysicsMaterialLoader.ts +++ b/packages/loader/src/PhysicsMaterialLoader.ts @@ -8,7 +8,7 @@ import { PhysicsMaterial } from "@galacean/engine-core"; -@resourceLoader(AssetType.PhysicsMaterial, ["mesh"]) +@resourceLoader(AssetType.PhysicsMaterial, ["physMat"]) class PhysicsMaterialLoader extends Loader { load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { return ( diff --git a/packages/loader/src/ProjectLoader.ts b/packages/loader/src/ProjectLoader.ts index 128ec56535..de0ce3807b 100644 --- a/packages/loader/src/ProjectLoader.ts +++ b/packages/loader/src/ProjectLoader.ts @@ -9,7 +9,7 @@ import { } from "@galacean/engine-core"; import { IProject } from "./resource-deserialize"; -@resourceLoader(AssetType.Project, ["proj"], false) +@resourceLoader(AssetType.Project, ["project"], false) class ProjectLoader extends Loader { load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { const { engine } = resourceManager; diff --git a/packages/loader/src/Texture2DContentRestorer.ts b/packages/loader/src/Texture2DContentRestorer.ts deleted file mode 100644 index 5a9cfcccbf..0000000000 --- a/packages/loader/src/Texture2DContentRestorer.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { AssetPromise, ContentRestorer, RequestConfig, Texture2D, request } from "@galacean/engine-core"; - -/** - * @internal - */ -export class Texture2DContentRestorer extends ContentRestorer { - constructor( - resource: Texture2D, - public url: string, - public requestConfig: RequestConfig - ) { - super(resource); - } - - override restoreContent(): AssetPromise { - return request(this.url, this.requestConfig).then((image) => { - const resource = this.resource; - resource.setImageSource(image); - resource.generateMipmaps(); - return resource; - }); - } -} diff --git a/packages/loader/src/Texture2DLoader.ts b/packages/loader/src/Texture2DLoader.ts index 16600f0f0a..127b37eb96 100644 --- a/packages/loader/src/Texture2DLoader.ts +++ b/packages/loader/src/Texture2DLoader.ts @@ -1,6 +1,7 @@ import { AssetPromise, AssetType, + ContentRestorer, LoadItem, Loader, RequestConfig, @@ -12,65 +13,117 @@ import { TextureWrapMode, resourceLoader } from "@galacean/engine-core"; -import { Texture2DContentRestorer } from "./Texture2DContentRestorer"; +import { decode } from "./resource-deserialize"; +import { FileHeader } from "./resource-deserialize/utils/FileHeader"; -@resourceLoader(AssetType.Texture2D, ["png", "jpg", "webp", "jpeg"]) +function loadImageFromBuffer(buffer: ArrayBuffer): AssetPromise { + return new AssetPromise((resolve, reject) => { + const blob = new Blob([buffer]); + const img = new Image(); + img.onload = () => { + URL.revokeObjectURL(img.src); + resolve(img); + }; + img.onerror = reject; + img.src = URL.createObjectURL(blob); + }); +} + +@resourceLoader(AssetType.Texture2D, ["png", "jpg", "webp", "jpeg", "tex"]) class Texture2DLoader extends Loader { override load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { + const url = item.url; + const requestConfig = { ...item, type: "arraybuffer" }; return new AssetPromise((resolve, reject, setTaskCompleteProgress, setTaskDetailProgress) => { - const url = item.url; - const requestConfig = { - ...item, - type: "image" - }; resourceManager // @ts-ignore - ._request(url, requestConfig) + ._request(url, requestConfig) .onProgress(setTaskCompleteProgress, setTaskDetailProgress) - .then((image) => { - const { - format = TextureFormat.R8G8B8A8, - anisoLevel, - wrapModeU, - wrapModeV, - filterMode, - isSRGBColorSpace = true, - mipmap = true - } = (item.params as Partial) ?? {}; - const { width, height } = image; - const engine = resourceManager.engine; + .then((buffer) => { + if (FileHeader.checkMagic(buffer)) { + decode(buffer, resourceManager.engine).then((texture) => { + resourceManager.addContentRestorer(new Texture2DContentRestorer(texture, url, requestConfig)); + resolve(texture); + }, reject); + } else { + loadImageFromBuffer(buffer).then((img) => { + const texture = this._createTexture(img, item, resourceManager); + resourceManager.addContentRestorer(new Texture2DContentRestorer(texture, url, requestConfig)); + resolve(texture); + }, reject); + } + }) + .catch(reject); + }); + } - const generateMipmap = TextureUtils.supportGenerateMipmapsWithCorrection( - engine, - width, - height, - format, - mipmap, - isSRGBColorSpace - ); + private _createTexture(img: HTMLImageElement, item: LoadItem, resourceManager: ResourceManager): Texture2D { + const { + format = TextureFormat.R8G8B8A8, + anisoLevel, + wrapModeU, + wrapModeV, + filterMode, + isSRGBColorSpace = true, + mipmap = true + } = (item.params as Partial) ?? {}; + const { width, height } = img; + const engine = resourceManager.engine; - const texture = new Texture2D(engine, width, height, format, generateMipmap, isSRGBColorSpace); + const generateMipmap = TextureUtils.supportGenerateMipmapsWithCorrection( + engine, + width, + height, + format, + mipmap, + isSRGBColorSpace + ); - texture.anisoLevel = anisoLevel ?? texture.anisoLevel; - texture.filterMode = filterMode ?? texture.filterMode; - texture.wrapModeU = wrapModeU ?? texture.wrapModeU; - texture.wrapModeV = wrapModeV ?? texture.wrapModeV; + const texture = new Texture2D(engine, width, height, format, generateMipmap, isSRGBColorSpace); + texture.anisoLevel = anisoLevel ?? texture.anisoLevel; + texture.filterMode = filterMode ?? texture.filterMode; + texture.wrapModeU = wrapModeU ?? texture.wrapModeU; + texture.wrapModeV = wrapModeV ?? texture.wrapModeV; + texture.setImageSource(img); + generateMipmap && texture.generateMipmaps(); - texture.setImageSource(image); - generateMipmap && texture.generateMipmaps(); + const url = item.url; + if (url.indexOf("data:") !== 0) { + texture.name = url.substring(url.lastIndexOf("/") + 1); + } - if (url.indexOf("data:") !== 0) { - const index = url.lastIndexOf("/"); - texture.name = url.substring(index + 1); - } + return texture; + } +} + +class Texture2DContentRestorer extends ContentRestorer { + constructor( + resource: Texture2D, + public url: string, + public requestConfig: RequestConfig + ) { + super(resource); + } - resourceManager.addContentRestorer(new Texture2DContentRestorer(texture, url, requestConfig)); - resolve(texture); + override restoreContent(): AssetPromise { + const texture = this.resource; + const engine = texture.engine; + return ( + engine.resourceManager + // @ts-ignore + ._request(this.url, this.requestConfig) + .then((buffer) => { + if (FileHeader.checkMagic(buffer)) { + return decode(buffer, engine, texture); + } else { + return loadImageFromBuffer(buffer).then((img) => { + texture.setImageSource(img); + texture.generateMipmaps(); + return texture; + }); + } }) - .catch((e) => { - reject(e); - }); - }); + ); } } diff --git a/packages/loader/src/TextureCubeLoader.ts b/packages/loader/src/TextureCubeLoader.ts index c5d286a55b..64398e5922 100644 --- a/packages/loader/src/TextureCubeLoader.ts +++ b/packages/loader/src/TextureCubeLoader.ts @@ -13,7 +13,7 @@ import { } from "@galacean/engine-core"; import { TextureCubeContentRestorer } from "./TextureCubeContentRestorer"; -@resourceLoader(AssetType.TextureCube, [""]) +@resourceLoader(AssetType.TextureCube, ["texCube"]) class TextureCubeLoader extends Loader { override load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { return new AssetPromise((resolve, reject) => { diff --git a/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts b/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts index 11a43f4d43..126d3cab2b 100644 --- a/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts +++ b/packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts @@ -153,7 +153,7 @@ export interface IEXTMeshoptCompressionSchema { } export interface IGalaceanMaterialRemap { - refId: string; + url: string; key?: string; isClone?: boolean; } diff --git a/packages/loader/src/resource-deserialize/index.ts b/packages/loader/src/resource-deserialize/index.ts index 1dbd8993ec..b50923d1cb 100644 --- a/packages/loader/src/resource-deserialize/index.ts +++ b/packages/loader/src/resource-deserialize/index.ts @@ -26,7 +26,6 @@ export function decode(arrayBuffer: ArrayBuffer, engine: Engine, ...args: any export * from "./resources/parser/HierarchyParser"; export * from "./resources/parser/ParserContext"; -export * from "./resources/scene/EditorTextureLoader"; export * from "./resources/scene/SceneParser"; export * from "./resources/schema"; diff --git a/packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts b/packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts index 8c2ef09f96..ba8c08c1d4 100644 --- a/packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts +++ b/packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts @@ -223,7 +223,7 @@ export abstract class HierarchyParser { let entityPromise: Promise; - if ((entityConfig).assetRefId) { + if ((entityConfig).assetUrl) { entityPromise = this._parsePrefab(entityConfig, engine); } else if ((entityConfig).strippedId) { entityPromise = this._parseStrippedEntity(entityConfig); @@ -245,13 +245,13 @@ export abstract class HierarchyParser { - const assetRefId: string = entityConfig.assetRefId; + const assetUrl: string = entityConfig.assetUrl; return ( engine.resourceManager // @ts-ignore .getResourceByRef({ - refId: assetRefId + url: assetUrl }) .then((prefabResource: PrefabResource | GLTFResource) => { const entity = @@ -310,7 +310,7 @@ export abstract class HierarchyParser { _setTaskCompleteProgress: (loaded: number, total: number) => void; /** @internal */ - _addDependentAsset(refID: string, promise: AssetPromise): void { + _addDependentAsset(url: string, promise: AssetPromise): void { const tasks = this._tasks; - if (tasks.has(refID)) return; + if (tasks.has(url)) return; ++this._total; - tasks.add(refID); + tasks.add(url); promise.finally(() => { ++this._loaded; this._setTaskCompleteProgress(this._loaded, this._total); diff --git a/packages/loader/src/resource-deserialize/resources/parser/ReflectionParser.ts b/packages/loader/src/resource-deserialize/resources/parser/ReflectionParser.ts index ef140f01f8..45bc1e2882 100644 --- a/packages/loader/src/resource-deserialize/resources/parser/ReflectionParser.ts +++ b/packages/loader/src/resource-deserialize/resources/parser/ReflectionParser.ts @@ -107,7 +107,7 @@ export class ReflectionParser { // reference object // @ts-ignore return context.resourceManager.getResourceByRef(value).then((resource) => { - if (context.type === ParserType.Prefab) { + if (resource && context.type === ParserType.Prefab) { // @ts-ignore context.resource._addDependenceAsset(resource); } @@ -144,22 +144,22 @@ export class ReflectionParser { private _getEntityByConfig(entityConfig: IEntity) { // @ts-ignore - const assetRefId: string = entityConfig.assetRefId; + const assetUrl: string = entityConfig.assetUrl; const engine = this._context.engine; - if (assetRefId) { + if (assetUrl) { return ( engine.resourceManager // @ts-ignore .getResourceByRef({ - refId: assetRefId, + url: assetUrl, key: (entityConfig as IRefEntity).key, isClone: (entityConfig as IRefEntity).isClone }) .then((entity) => { // @ts-ignore - const resource = engine.resourceManager._objectPool[assetRefId]; - if (this._context.type === ParserType.Prefab) { + const resource = engine.resourceManager._objectPool[assetUrl]; + if (resource && this._context.type === ParserType.Prefab) { // @ts-ignore this._context.resource._addDependenceAsset(resource); } @@ -183,7 +183,7 @@ export class ReflectionParser { } private static _isAssetRef(value: any): value is IAssetRef { - return value["refId"] !== undefined; + return value["url"] !== undefined; } private static _isEntityRef(value: any): value is IEntityRef { diff --git a/packages/loader/src/resource-deserialize/resources/scene/EditorTextureLoader.ts b/packages/loader/src/resource-deserialize/resources/scene/EditorTextureLoader.ts deleted file mode 100644 index 5b4c336ffd..0000000000 --- a/packages/loader/src/resource-deserialize/resources/scene/EditorTextureLoader.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { - AssetPromise, - ContentRestorer, - Loader, - LoadItem, - resourceLoader, - ResourceManager, - Texture2D -} from "@galacean/engine-core"; -import { RequestConfig } from "@galacean/engine-core/types/asset/request"; -import { decode } from "../.."; - -@resourceLoader("EditorTexture2D", ["prefab"], true) -export class EditorTextureLoader extends Loader { - load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { - const requestConfig = { - ...item, - type: "arraybuffer" - }; - const url = item.url; - return new AssetPromise((resolve, reject) => { - resourceManager - // @ts-ignore - ._request(url, requestConfig) - .then((data) => { - decode(data, resourceManager.engine).then((texture) => { - resourceManager.addContentRestorer(new EditorTexture2DContentRestorer(texture, url, requestConfig)); - resolve(texture); - }); - }) - .catch(reject); - }); - } -} - -class EditorTexture2DContentRestorer extends ContentRestorer { - constructor( - resource: Texture2D, - public url: string, - public requestConfig: RequestConfig - ) { - super(resource); - } - - override restoreContent(): AssetPromise { - const texture = this.resource; - const engine = texture.engine; - return ( - engine.resourceManager - // @ts-ignore - ._request(this.url, this.requestConfig) - .then((data) => decode(data, engine, texture)) - ); - } -} diff --git a/packages/loader/src/resource-deserialize/resources/scene/SceneParser.ts b/packages/loader/src/resource-deserialize/resources/scene/SceneParser.ts index 8c3c5b2ee7..48041b0ee0 100644 --- a/packages/loader/src/resource-deserialize/resources/scene/SceneParser.ts +++ b/packages/loader/src/resource-deserialize/resources/scene/SceneParser.ts @@ -29,11 +29,11 @@ export class SceneParser extends HierarchyParserentity).assetRefId) { + if (!!(entity).assetUrl) { const context = this.context; - const { assetRefId: refId, key } = entity; + const { assetUrl: url, key } = entity; // @ts-ignore - context._addDependentAsset(refId, context.resourceManager.getResourceByRef({ refId, key })); + context._addDependentAsset(url, context.resourceManager.getResourceByRef({ url, key })); } else if ((entity).strippedId) { continue; } else { @@ -96,7 +96,7 @@ export class SceneParser extends HierarchyParser { return new AssetPromise((resolve, reject) => { - const objectId = bufferReader.nextStr(); + const url = bufferReader.nextStr(); const mipmap = !!bufferReader.nextUint8(); const filterMode = bufferReader.nextUint8(); const anisoLevel = bufferReader.nextUint8(); @@ -38,7 +42,7 @@ export class Texture2DDecoder { } } // @ts-ignore - engine.resourceManager._objectPool[objectId] = texture2D; + engine.resourceManager._objectPool[url] = texture2D; resolve(texture2D); } else { const blob = new window.Blob([imagesData[0]]); diff --git a/packages/loader/src/resource-deserialize/utils/FileHeader.ts b/packages/loader/src/resource-deserialize/utils/FileHeader.ts index 94f0501aa9..25f69f1c82 100644 --- a/packages/loader/src/resource-deserialize/utils/FileHeader.ts +++ b/packages/loader/src/resource-deserialize/utils/FileHeader.ts @@ -1,20 +1,37 @@ import { Utils } from "@galacean/engine-core"; +/** + * Binary format: [MAGIC(4B)] [totalLength(4B)] [version(1B)] [typeLen(2B)] [type] [nameLen(2B)] [name] [data...] + */ export class FileHeader { + static readonly MAGIC = 0x4e434c47; // "GLCN" in little-endian + totalLength: number = 0; version: number = 0; type: string = ""; name: string = ""; headerLength: number = 0; + static checkMagic(arrayBuffer: ArrayBuffer): boolean { + if (arrayBuffer.byteLength < 4) return false; + const view = new DataView(arrayBuffer); + return view.getUint32(0, true) === FileHeader.MAGIC; + } + static decode(arrayBuffer: ArrayBuffer): FileHeader { const dataView = new DataView(arrayBuffer); - const totalLen = dataView.getUint32(0, true); - const fileVersion = dataView.getUint8(4); - const typeLen = dataView.getUint16(5, true); - const typeUint8Array = new Uint8Array(arrayBuffer, 7, typeLen); - const nameLen = dataView.getUint16(7 + typeLen, true); - const nameUint8Array = new Uint8Array(arrayBuffer, 9 + typeLen, nameLen); + + if (!FileHeader.checkMagic(arrayBuffer)) { + throw new Error("Invalid Galacean binary file: missing GLCN magic header."); + } + + const offset = 4; + const totalLen = dataView.getUint32(offset, true); + const fileVersion = dataView.getUint8(offset + 4); + const typeLen = dataView.getUint16(offset + 5, true); + const typeUint8Array = new Uint8Array(arrayBuffer, offset + 7, typeLen); + const nameLen = dataView.getUint16(offset + 7 + typeLen, true); + const nameUint8Array = new Uint8Array(arrayBuffer, offset + 9 + typeLen, nameLen); const name = Utils.decodeText(nameUint8Array); const type = Utils.decodeText(typeUint8Array); @@ -23,7 +40,7 @@ export class FileHeader { header.name = name; header.type = type; header.version = fileVersion; - header.headerLength = nameUint8Array.byteLength + typeUint8Array.byteLength + 9; + header.headerLength = offset + nameUint8Array.byteLength + typeUint8Array.byteLength + 9; return header; } diff --git a/tests/src/core/DeviceLost.test.ts b/tests/src/core/DeviceLost.test.ts index 07ee54b996..46c95ac321 100644 --- a/tests/src/core/DeviceLost.test.ts +++ b/tests/src/core/DeviceLost.test.ts @@ -1,4 +1,14 @@ -import { AmbientLight, AssetType, BlinnPhongMaterial, Camera, DirectLight, MeshRenderer, PrimitiveMesh, Texture2D, TextureCube } from "@galacean/engine-core"; +import { + AmbientLight, + AssetType, + BlinnPhongMaterial, + Camera, + DirectLight, + MeshRenderer, + PrimitiveMesh, + Texture2D, + TextureCube +} from "@galacean/engine-core"; import "@galacean/engine-loader"; import { WebGLEngine } from "@galacean/engine-rhi-webgl"; import { describe, expect, it } from "vitest"; @@ -11,7 +21,6 @@ describe("Device lost test", function () { it("Force lost and restore test", async () => { const engine = await WebGLEngine.create({ canvas: canvasDOM }); - // Get scene and create root entity. const scene = engine.sceneManager.activeScene; const rootEntity = scene.createRootEntity("Root"); @@ -42,30 +51,27 @@ describe("Device lost test", function () { const ambientLight = await resourceManager.load({ url: "https://mdn.alipayobjects.com/oasis_be/afts/file/A*t1inRbPh6VQAAAAAAAAAAAAADkp5AQ/ambient.json", type: AssetType.Env - }) + }); const textureCube = await engine.resourceManager.load({ url: "https://gw.alipayobjects.com/os/bmw-prod/10c5d68d-8580-4bd9-8795-6f1035782b94.bin", // sunset_1K type: AssetType.HDR - }) - const ktx2Texture = await resourceManager.load( - { - url: "https://mdn.alipayobjects.com/oasis_be/afts/img/A*iaD4QaUJRKoAAAAAAAAAAAAADkp5AQ/original/DefaultTexture.ktx2", - type: AssetType.KTX2 - } - ) + }); + const ktx2Texture = await resourceManager.load({ + url: "https://mdn.alipayobjects.com/oasis_be/afts/img/A*iaD4QaUJRKoAAAAAAAAAAAAADkp5AQ/original/DefaultTexture.ktx2", + type: AssetType.KTX2 + }); const editorTexture = await resourceManager.load({ - url: "https://mdn.alipayobjects.com/oasis_be/afts/file/A*dOzQRoS72LgAAAAAAAAAAAAAekp5AQ/ImageTexture.json", - type: "EditorTexture2D" - }) - + url: "https://mdn.alipayobjects.com/oasis_be/afts/file/A*oFd_T4ffoUMAAAAAQ8AAAAgAekp5AQ/Internal/Material/Internal/Material/DefaultTexture.tex", + type: AssetType.Texture2D + }); await new Promise((resolve) => { // Listening context devicelost and devicerestored - console.log('new Promise'); + console.log("new Promise"); engine.once("devicelost", () => { - console.log('context lost'); + console.log("context lost"); engine.once("devicerestored", () => { - console.log('context restored'); + console.log("context restored"); resolve(null); }); // 模拟器不支持上下文恢复,此处直接调用代码模拟丢失与恢复 @@ -74,12 +80,11 @@ describe("Device lost test", function () { }); // @ts-ignore engine._onDeviceLost(); - }) + }); expect(ambientLight.specularTexture.isContentLost).to.equal(false); expect(ktx2Texture.isContentLost).to.equal(false); expect(textureCube.isContentLost).to.equal(false); expect(editorTexture.isContentLost).to.equal(false); - }); }); diff --git a/tests/src/core/resource/ResourceManager.test.ts b/tests/src/core/resource/ResourceManager.test.ts index aeb1fabeff..0e76ae45d5 100644 --- a/tests/src/core/resource/ResourceManager.test.ts +++ b/tests/src/core/resource/ResourceManager.test.ts @@ -82,7 +82,7 @@ describe("ResourceManager", () => { it("invalid q case", async () => { const loadRes = await engine.resourceManager.load({ // contains invalid q value cdn url. - url: "https://mdn.alipayobjects.com/huamei_aftkdx/afts/file/A*_Ao1QZtL9fMAAAAAAAAAAAAADteEAQ/mock-project.json", + url: "https://mdn.alipayobjects.com/rms/afts/file/A*sX29TKhEzq4AAAAAQLAAAAgAehQnAQ/project.json", type: AssetType.Project }); expect(loadRes).to.equal(undefined); diff --git a/tests/src/loader/SceneParser.test.ts b/tests/src/loader/SceneParser.test.ts index db7728112e..157a767f64 100644 --- a/tests/src/loader/SceneParser.test.ts +++ b/tests/src/loader/SceneParser.test.ts @@ -23,7 +23,7 @@ describe("ProjectLoader Component Reference Tests", function () { await engine.resourceManager.load({ type: AssetType.Project, // button.Color.target be deleted - url: "https://mdn.alipayobjects.com/oasis_be/afts/file/A*hPs1Q4KdkBsAAAAAQNAAAAgAekp5AQ/project.json" + url: "https://mdn.alipayobjects.com/rms/afts/file/A*6GoSSK-ifQkAAAAAQMAAAAgAehQnAQ/project.json" }); const scene = engine.sceneManager.scenes[0];