playcanvas
Version:
PlayCanvas WebGL game engine
185 lines (182 loc) • 5.7 kB
JavaScript
import { Mat4 } from '../../../core/math/mat4.js';
import { Vec2 } from '../../../core/math/vec2.js';
import { Entity } from '../../entity.js';
import { SCALEMODE_NONE, SCALEMODE_BLEND } from './constants.js';
import { Component } from '../component.js';
var _transform = new Mat4();
class ScreenComponent extends Component {
syncDrawOrder() {
this.system.queueDrawOrderSync(this.entity.getGuid(), this._processDrawOrderSync, this);
}
_recurseDrawOrderSync(e, i) {
if (!(e instanceof Entity)) {
return i;
}
if (e.element) {
var prevDrawOrder = e.element.drawOrder;
e.element.drawOrder = i++;
if (e.element._batchGroupId >= 0 && prevDrawOrder !== e.element.drawOrder) {
var _this_system_app_batcher;
(_this_system_app_batcher = this.system.app.batcher) == null ? void 0 : _this_system_app_batcher.markGroupDirty(e.element._batchGroupId);
}
}
if (e.particlesystem) {
e.particlesystem.drawOrder = i++;
}
var children = e.children;
for(var j = 0; j < children.length; j++){
i = this._recurseDrawOrderSync(children[j], i);
}
return i;
}
_processDrawOrderSync() {
var i = 1;
this._recurseDrawOrderSync(this.entity, i);
this.fire('syncdraworder');
}
_calcProjectionMatrix() {
var w = this._resolution.x / this.scale;
var h = this._resolution.y / this.scale;
var left = 0;
var right = w;
var bottom = -h;
var top = 0;
var near = 1;
var far = -1;
this._screenMatrix.setOrtho(left, right, bottom, top, near, far);
if (!this._screenSpace) {
_transform.setScale(0.5 * w, 0.5 * h, 1);
this._screenMatrix.mul2(_transform, this._screenMatrix);
}
}
_updateScale() {
this.scale = this._calcScale(this._resolution, this.referenceResolution);
}
_calcScale(resolution, referenceResolution) {
var lx = Math.log2((resolution.x || 1) / referenceResolution.x);
var ly = Math.log2((resolution.y || 1) / referenceResolution.y);
return Math.pow(2, lx * (1 - this._scaleBlend) + ly * this._scaleBlend);
}
_onResize(width, height) {
if (this._screenSpace) {
this._resolution.set(width, height);
this.resolution = this._resolution;
}
}
_bindElement(element) {
this._elements.add(element);
}
_unbindElement(element) {
this._elements.delete(element);
}
onRemove() {
this.system.app.graphicsDevice.off('resizecanvas', this._onResize, this);
this.fire('remove');
this._elements.forEach((element)=>element._onScreenRemove());
this._elements.clear();
this.off();
}
set resolution(value) {
if (!this._screenSpace) {
this._resolution.set(value.x, value.y);
} else {
this._resolution.set(this.system.app.graphicsDevice.width, this.system.app.graphicsDevice.height);
}
this._updateScale();
this._calcProjectionMatrix();
if (!this.entity._dirtyLocal) {
this.entity._dirtifyLocal();
}
this.fire('set:resolution', this._resolution);
this._elements.forEach((element)=>element._onScreenResize(this._resolution));
}
get resolution() {
return this._resolution;
}
set referenceResolution(value) {
this._referenceResolution.set(value.x, value.y);
this._updateScale();
this._calcProjectionMatrix();
if (!this.entity._dirtyLocal) {
this.entity._dirtifyLocal();
}
this.fire('set:referenceresolution', this._resolution);
this._elements.forEach((element)=>element._onScreenResize(this._resolution));
}
get referenceResolution() {
if (this._scaleMode === SCALEMODE_NONE) {
return this._resolution;
}
return this._referenceResolution;
}
set screenSpace(value) {
this._screenSpace = value;
if (this._screenSpace) {
this._resolution.set(this.system.app.graphicsDevice.width, this.system.app.graphicsDevice.height);
}
this.resolution = this._resolution;
if (!this.entity._dirtyLocal) {
this.entity._dirtifyLocal();
}
this.fire('set:screenspace', this._screenSpace);
this._elements.forEach((element)=>element._onScreenSpaceChange());
}
get screenSpace() {
return this._screenSpace;
}
set scaleMode(value) {
if (value !== SCALEMODE_NONE && value !== SCALEMODE_BLEND) {
value = SCALEMODE_NONE;
}
if (!this._screenSpace && value !== SCALEMODE_NONE) {
value = SCALEMODE_NONE;
}
this._scaleMode = value;
this.resolution = this._resolution;
this.fire('set:scalemode', this._scaleMode);
}
get scaleMode() {
return this._scaleMode;
}
set scaleBlend(value) {
this._scaleBlend = value;
this._updateScale();
this._calcProjectionMatrix();
if (!this.entity._dirtyLocal) {
this.entity._dirtifyLocal();
}
this.fire('set:scaleblend', this._scaleBlend);
this._elements.forEach((element)=>element._onScreenResize(this._resolution));
}
get scaleBlend() {
return this._scaleBlend;
}
set priority(value) {
if (value > 0xFF) {
value = 0xFF;
}
if (this._priority === value) {
return;
}
this._priority = value;
this.syncDrawOrder();
}
get priority() {
return this._priority;
}
constructor(system, entity){
super(system, entity);
this._resolution = new Vec2(640, 320);
this._referenceResolution = new Vec2(640, 320);
this._scaleMode = SCALEMODE_NONE;
this.scale = 1;
this._scaleBlend = 0.5;
this._priority = 0;
this._screenSpace = false;
this.cull = this._screenSpace;
this._screenMatrix = new Mat4();
this._elements = new Set();
system.app.graphicsDevice.on('resizecanvas', this._onResize, this);
}
}
export { ScreenComponent };