mirror of
https://github.com/galacean/engine.git
synced 2026-06-20 20:06:02 +08:00
* fix: prefab refcount error
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Engine, Entity } from "@galacean/engine-core";
|
||||
import { IEntity, IHierarchyFile, ParserContext, ParserType } from "../resource-deserialize";
|
||||
import { HierarchyParser } from "../resource-deserialize/resources/parser/HierarchyParser";
|
||||
import { PrefabResource } from "./PrefabResource";
|
||||
import { IHierarchyFile, ParserContext, ParserType } from "../resource-deserialize";
|
||||
|
||||
export class PrefabParser extends HierarchyParser<PrefabResource, ParserContext<IHierarchyFile, Entity>> {
|
||||
static parse(engine: Engine, url: string, data: IHierarchyFile): Promise<PrefabResource> {
|
||||
@@ -20,6 +20,13 @@ export class PrefabParser extends HierarchyParser<PrefabResource, ParserContext<
|
||||
super(data, context);
|
||||
}
|
||||
|
||||
protected override _applyEntityData(entity: Entity, entityConfig: IEntity = {}): Entity {
|
||||
super._applyEntityData(entity, entityConfig);
|
||||
// @ts-ignore
|
||||
entity._markAsTemplate(this.context.resource);
|
||||
return entity;
|
||||
}
|
||||
|
||||
protected override _handleRootEntity(id: string): void {
|
||||
this.prefabResource._root = this.context.entityMap.get(id);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,23 @@ export abstract class HierarchyParser<T extends Scene | PrefabResource, V extend
|
||||
.catch(this._reject);
|
||||
}
|
||||
|
||||
protected _applyEntityData(entity: Entity, entityConfig: IEntity = {}): Entity {
|
||||
entity.isActive = entityConfig.isActive ?? entity.isActive;
|
||||
entity.name = entityConfig.name ?? entity.name;
|
||||
const transform = entity.transform;
|
||||
const transformConfig = entityConfig.transform;
|
||||
if (transformConfig) {
|
||||
this._reflectionParser.parsePropsAndMethods(transform, transformConfig);
|
||||
} else {
|
||||
const { position, rotation, scale } = entityConfig;
|
||||
if (position) transform.position.copyFrom(position);
|
||||
if (rotation) transform.rotation.copyFrom(rotation);
|
||||
if (scale) transform.scale.copyFrom(scale);
|
||||
}
|
||||
if (entityConfig.layer) entity.layer = entityConfig.layer;
|
||||
return entity;
|
||||
}
|
||||
|
||||
protected abstract _handleRootEntity(id: string): void;
|
||||
protected abstract _clearAndResolve(): Scene | PrefabResource;
|
||||
|
||||
@@ -302,23 +319,6 @@ export abstract class HierarchyParser<T extends Scene | PrefabResource, V extend
|
||||
}
|
||||
}
|
||||
|
||||
private _applyEntityData(entity: Entity, entityConfig: IEntity = {}): Entity {
|
||||
entity.isActive = entityConfig.isActive ?? entity.isActive;
|
||||
entity.name = entityConfig.name ?? entity.name;
|
||||
const transform = entity.transform;
|
||||
const transformConfig = entityConfig.transform;
|
||||
if (transformConfig) {
|
||||
this._reflectionParser.parsePropsAndMethods(transform, transformConfig);
|
||||
} else {
|
||||
const { position, rotation, scale } = entityConfig;
|
||||
if (position) transform.position.copyFrom(position);
|
||||
if (rotation) transform.rotation.copyFrom(rotation);
|
||||
if (scale) transform.scale.copyFrom(scale);
|
||||
}
|
||||
if (entityConfig.layer) entity.layer = entityConfig.layer;
|
||||
return entity;
|
||||
}
|
||||
|
||||
private _generateInstanceContext(entity: Entity, context: ParserContext<IHierarchyFile, Entity>, path: string) {
|
||||
const { entityMap, components } = context;
|
||||
const componentsMap = {};
|
||||
|
||||
54
tests/src/loader/PrefabResource.test.ts
Normal file
54
tests/src/loader/PrefabResource.test.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { expect, beforeAll, afterAll, describe, it } from "vitest";
|
||||
import { WebGLEngine } from "@galacean/engine-rhi-webgl";
|
||||
import type { IHierarchyFile } from "@galacean/engine-loader";
|
||||
import { PrefabParser } from "../../../packages/loader/src/prefab/PrefabParser";
|
||||
|
||||
let engine: WebGLEngine;
|
||||
|
||||
beforeAll(async () => {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = 256;
|
||||
canvas.height = 256;
|
||||
engine = await WebGLEngine.create({ canvas });
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
engine?.destroy();
|
||||
});
|
||||
|
||||
describe("PrefabResource refCount", () => {
|
||||
it("should increase and decrease with instantiated entities", async () => {
|
||||
const prefabData: IHierarchyFile = {
|
||||
entities: [
|
||||
{
|
||||
id: "0",
|
||||
name: "root",
|
||||
components: [],
|
||||
children: ["1"]
|
||||
},
|
||||
{
|
||||
id: "1",
|
||||
name: "child",
|
||||
parent: "0",
|
||||
components: []
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const prefab = await PrefabParser.parse(engine, "prefab.json", prefabData);
|
||||
|
||||
expect(prefab.refCount).toBe(0);
|
||||
|
||||
const instance1 = prefab.instantiate();
|
||||
const instance2 = prefab.instantiate();
|
||||
|
||||
// One ref count per templated entity in each instance (root + child).
|
||||
expect(prefab.refCount).toBe(4);
|
||||
|
||||
instance1.destroy();
|
||||
expect(prefab.refCount).toBe(2);
|
||||
|
||||
instance2.destroy();
|
||||
expect(prefab.refCount).toBe(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user