playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
113 lines (112 loc) • 3.82 kB
JavaScript
import { IndexedList } from "../../../core/indexed-list.js";
import { Vec2 } from "../../../core/math/vec2.js";
import { Component } from "../component.js";
import { ComponentSystem } from "../system.js";
import { ScreenComponent } from "./component.js";
import { ScreenComponentData } from "./data.js";
const _schema = ["enabled"];
class ScreenComponentSystem extends ComponentSystem {
constructor(app) {
super(app);
this.id = "screen";
this.ComponentType = ScreenComponent;
this.DataType = ScreenComponentData;
this.schema = _schema;
this.windowResolution = new Vec2();
this._drawOrderSyncQueue = new IndexedList();
this.app.graphicsDevice.on("resizecanvas", this._onResize, this);
this.app.systems.on("update", this._onUpdate, this);
this.on("beforeremove", this.onRemoveComponent, this);
}
initializeComponentData(component, data, properties) {
if (data.priority !== void 0) component.priority = data.priority;
if (data.screenSpace !== void 0) component.screenSpace = data.screenSpace;
component.cull = component.screenSpace;
if (data.scaleMode !== void 0) component.scaleMode = data.scaleMode;
if (data.scaleBlend !== void 0) component.scaleBlend = data.scaleBlend;
if (data.resolution !== void 0) {
if (data.resolution instanceof Vec2) {
component._resolution.copy(data.resolution);
} else {
component._resolution.set(data.resolution[0], data.resolution[1]);
}
component.resolution = component._resolution;
}
if (data.referenceResolution !== void 0) {
if (data.referenceResolution instanceof Vec2) {
component._referenceResolution.copy(data.referenceResolution);
} else {
component._referenceResolution.set(data.referenceResolution[0], data.referenceResolution[1]);
}
component.referenceResolution = component._referenceResolution;
}
this._updateDescendantElements(component.entity, component.entity);
component.syncDrawOrder();
super.initializeComponentData(component, data, _schema);
}
_updateDescendantElements(entity, screenEntity) {
const children = entity.children;
for (let i = 0; i < children.length; i++) {
const child = children[i];
if (child.element && !child.element.screen) {
child.element._updateScreen(screenEntity);
}
if (!child.screen) {
this._updateDescendantElements(child, screenEntity);
}
}
}
destroy() {
super.destroy();
this.app.graphicsDevice.off("resizecanvas", this._onResize, this);
this.app.systems.off("update", this._onUpdate, this);
}
_onUpdate(dt) {
const components = this.store;
for (const id in components) {
if (components[id].entity.screen.update) components[id].entity.screen.update(dt);
}
}
_onResize(width, height) {
this.windowResolution.x = width;
this.windowResolution.y = height;
}
cloneComponent(entity, clone) {
const screen = entity.screen;
return this.addComponent(clone, {
enabled: screen.enabled,
screenSpace: screen.screenSpace,
scaleMode: screen.scaleMode,
scaleBlend: screen.scaleBlend,
priority: screen.priority,
resolution: screen.resolution.clone(),
referenceResolution: screen.referenceResolution.clone()
});
}
onRemoveComponent(entity, component) {
component.onRemove();
}
processDrawOrderSyncQueue() {
const list = this._drawOrderSyncQueue.list();
for (let i = 0; i < list.length; i++) {
const item = list[i];
item.callback.call(item.scope);
}
this._drawOrderSyncQueue.clear();
}
queueDrawOrderSync(id, fn, scope) {
if (!this._drawOrderSyncQueue.list().length) {
this.app.once("prerender", this.processDrawOrderSyncQueue, this);
}
if (!this._drawOrderSyncQueue.has(id)) {
this._drawOrderSyncQueue.push(id, {
callback: fn,
scope
});
}
}
}
Component._buildAccessors(ScreenComponent.prototype, _schema);
export {
ScreenComponentSystem
};