playcanvas
Version:
PlayCanvas WebGL game engine
194 lines (191 loc) • 6.41 kB
JavaScript
import { Color } from '../../../core/math/color.js';
import { PIXELFORMAT_SRGBA8, CULLFACE_NONE } from '../../../platform/graphics/constants.js';
import { Texture } from '../../../platform/graphics/texture.js';
import { BLEND_PREMULTIPLIED, SPRITE_RENDERMODE_SLICED, SPRITE_RENDERMODE_TILED } from '../../../scene/constants.js';
import { StandardMaterial } from '../../../scene/materials/standard-material.js';
import { Component } from '../component.js';
import { ComponentSystem } from '../system.js';
import { SpriteComponent } from './component.js';
import { SpriteComponentData } from './data.js';
const _schema = [
'enabled'
];
class SpriteComponentSystem extends ComponentSystem {
constructor(app){
super(app);
this.id = 'sprite';
this.ComponentType = SpriteComponent;
this.DataType = SpriteComponentData;
this.schema = _schema;
this._defaultTexture = null;
this._defaultMaterial = null;
this._default9SlicedMaterialSlicedMode = null;
this._default9SlicedMaterialTiledMode = null;
this.app.systems.on('update', this.onUpdate, this);
this.on('beforeremove', this.onBeforeRemove, this);
}
set defaultMaterial(material) {
this._defaultMaterial = material;
}
get defaultMaterial() {
if (!this._defaultMaterial) {
const texture = new Texture(this.app.graphicsDevice, {
width: 1,
height: 1,
format: PIXELFORMAT_SRGBA8,
name: 'sprite'
});
const pixels = new Uint8Array(texture.lock());
pixels[0] = pixels[1] = pixels[2] = pixels[3] = 255;
texture.unlock();
const material = new StandardMaterial();
material.diffuse.set(0, 0, 0);
material.emissive.set(1, 1, 1);
material.emissiveMap = texture;
material.opacityMap = texture;
material.opacityMapChannel = 'a';
material.useLighting = false;
material.useTonemap = false;
material.useFog = false;
material.useSkybox = false;
material.blendType = BLEND_PREMULTIPLIED;
material.depthWrite = false;
material.pixelSnap = false;
material.cull = CULLFACE_NONE;
material.update();
this._defaultTexture = texture;
this._defaultMaterial = material;
}
return this._defaultMaterial;
}
set default9SlicedMaterialSlicedMode(material) {
this._default9SlicedMaterialSlicedMode = material;
}
get default9SlicedMaterialSlicedMode() {
if (!this._default9SlicedMaterialSlicedMode) {
const material = this.defaultMaterial.clone();
material.nineSlicedMode = SPRITE_RENDERMODE_SLICED;
material.update();
this._default9SlicedMaterialSlicedMode = material;
}
return this._default9SlicedMaterialSlicedMode;
}
set default9SlicedMaterialTiledMode(material) {
this._default9SlicedMaterialTiledMode = material;
}
get default9SlicedMaterialTiledMode() {
if (!this._default9SlicedMaterialTiledMode) {
const material = this.defaultMaterial.clone();
material.nineSlicedMode = SPRITE_RENDERMODE_TILED;
material.update();
this._default9SlicedMaterialTiledMode = material;
}
return this._default9SlicedMaterialTiledMode;
}
destroy() {
super.destroy();
this.app.systems.off('update', this.onUpdate, this);
if (this._defaultTexture) {
this._defaultTexture.destroy();
this._defaultTexture = null;
}
}
initializeComponentData(component, data, properties) {
if (data.enabled !== undefined) {
component.enabled = data.enabled;
}
component.type = data.type;
if (data.layers && Array.isArray(data.layers)) {
component.layers = data.layers.slice(0);
}
if (data.drawOrder !== undefined) {
component.drawOrder = data.drawOrder;
}
if (data.color !== undefined) {
if (data.color instanceof Color) {
component.color.set(data.color.r, data.color.g, data.color.b, data.opacity ?? 1);
} else {
component.color.set(data.color[0], data.color[1], data.color[2], data.opacity ?? 1);
}
component.color = component.color;
}
if (data.opacity !== undefined) {
component.opacity = data.opacity;
}
if (data.flipX !== undefined) {
component.flipX = data.flipX;
}
if (data.flipY !== undefined) {
component.flipY = data.flipY;
}
if (data.width !== undefined) {
component.width = data.width;
}
if (data.height !== undefined) {
component.height = data.height;
}
if (data.spriteAsset !== undefined) {
component.spriteAsset = data.spriteAsset;
}
if (data.sprite) {
component.sprite = data.sprite;
}
if (data.frame !== undefined) {
component.frame = data.frame;
}
if (data.clips) {
for(const name in data.clips){
component.addClip(data.clips[name]);
}
}
if (data.speed !== undefined) {
component.speed = data.speed;
}
if (data.autoPlayClip) {
component.autoPlayClip = data.autoPlayClip;
}
component.batchGroupId = data.batchGroupId === undefined || data.batchGroupId === null ? -1 : data.batchGroupId;
super.initializeComponentData(component, data, properties);
}
cloneComponent(entity, clone) {
const source = entity.sprite;
return this.addComponent(clone, {
enabled: source.enabled,
type: source.type,
spriteAsset: source.spriteAsset,
sprite: source.sprite,
width: source.width,
height: source.height,
frame: source.frame,
color: source.color.clone(),
opacity: source.opacity,
flipX: source.flipX,
flipY: source.flipY,
speed: source.speed,
clips: source.clips,
autoPlayClip: source.autoPlayClip,
batchGroupId: source.batchGroupId,
drawOrder: source.drawOrder,
layers: source.layers.slice(0)
});
}
onUpdate(dt) {
const components = this.store;
for(const id in components){
if (components.hasOwnProperty(id)) {
const component = components[id];
if (component.data.enabled && component.entity.enabled) {
const sprite = component.entity.sprite;
if (sprite._currentClip) {
sprite._currentClip._update(dt);
}
}
}
}
}
onBeforeRemove(entity, component) {
component.onDestroy();
}
}
Component._buildAccessors(SpriteComponent.prototype, _schema);
export { SpriteComponentSystem };