Skip to content

Commit

Permalink
Fix component denpendency bug (galacean#1427)
Browse files Browse the repository at this point in the history
* fix: component dependencies bug

* test: add component dependencies unit test
  • Loading branch information
GuoLei1990 authored Mar 23, 2023
1 parent 5dc198f commit 74df8aa
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 16 deletions.
38 changes: 22 additions & 16 deletions packages/core/src/ComponentsDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,40 @@ export class ComponentsDependencies {
/**
* @internal
*/
static _addCheck(entity: Entity, target: ComponentConstructor): void {
const dependentInfo = ComponentsDependencies._dependenciesMap.get(target);
if (dependentInfo) {
const { components, mode } = dependentInfo;
for (let i = 0, n = components.length; i < n; i++) {
const dependentComponent = components[i];
if (!entity.getComponent(dependentComponent)) {
if (mode === DependentMode.AutoAdd) {
entity.addComponent(dependentComponent);
} else {
throw `Should add ${dependentComponent.name} before adding ${target.name}`;
static _addCheck(entity: Entity, type: ComponentConstructor): void {
while (type !== Component) {
const dependentInfo = ComponentsDependencies._dependenciesMap.get(type);
if (dependentInfo) {
const { components, mode } = dependentInfo;
for (let i = 0, n = components.length; i < n; i++) {
const dependentComponent = components[i];
if (!entity.getComponent(dependentComponent)) {
if (mode === DependentMode.AutoAdd) {
entity.addComponent(dependentComponent);
} else {
throw `Should add ${dependentComponent.name} before adding ${type.name}`;
}
}
}
}
type = Object.getPrototypeOf(type);
}
}

/**
* @internal
*/
static _removeCheck(entity: Entity, type: ComponentConstructor): void {
const invDependencies = ComponentsDependencies._invDependenciesMap.get(type);
if (invDependencies) {
for (let i = 0, len = invDependencies.length; i < len; i++) {
if (entity.getComponent(invDependencies[i])) {
throw `Should remove ${invDependencies[i].name} before adding ${type.name}`;
while (type !== Component) {
const invDependencies = ComponentsDependencies._invDependenciesMap.get(type);
if (invDependencies) {
for (let i = 0, len = invDependencies.length; i < len; i++) {
if (entity.getComponent(invDependencies[i])) {
throw `Should remove ${invDependencies[i].name} before adding ${type.name}`;
}
}
}
type = Object.getPrototypeOf(type);
}
}

Expand Down
36 changes: 36 additions & 0 deletions tests/src/core/CompomentDependencies.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Camera, dependentComponents, DependentMode, Entity, MeshRenderer, Script } from "@oasis-engine/core";
import { WebGLEngine } from "@oasis-engine/rhi-webgl";
import { expect } from "chai";

const canvasDOM = document.createElement("canvas");
canvasDOM.width = 1024;
canvasDOM.height = 1024;

describe("Component dependencies test", function () {
let entity: Entity;
let camera: Camera;
before(() => {
const engine = new WebGLEngine(canvasDOM);
entity = engine.sceneManager.activeScene.createRootEntity();
camera = entity.addComponent(Camera);
});

it("Super dependencies add check", () => {
expect(() => {
entity.addComponent(CustomScriptB);
}).throw("Should add MeshRenderer before adding CustomScriptA");
});

it("Super dependencies remove check", () => {
expect(() => {
const meshRenderer = entity.addComponent(MeshRenderer);
entity.addComponent(CustomScriptB);
meshRenderer.destroy();
}).throw("Should remove CustomScriptA before adding MeshRenderer");
});
});

@dependentComponents(DependentMode.CheckOnly, MeshRenderer)
export class CustomScriptA extends Script {}

export class CustomScriptB extends CustomScriptA {}

0 comments on commit 74df8aa

Please sign in to comment.