UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

201 lines (200 loc) 6.5 kB
import { Color } from "../../../core/math/color.js"; import { CULLFACE_NONE, PIXELFORMAT_SRGBA8 } 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 { /** * Create a new SpriteComponentSystem instance. * * @param {AppBase} app - The application. * @ignore */ 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 !== void 0) { component.enabled = data.enabled; } component.type = data.type; if (data.layers && Array.isArray(data.layers)) { component.layers = data.layers.slice(0); } if (data.drawOrder !== void 0) { component.drawOrder = data.drawOrder; } if (data.color !== void 0) { 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 !== void 0) { component.opacity = data.opacity; } if (data.flipX !== void 0) { component.flipX = data.flipX; } if (data.flipY !== void 0) { component.flipY = data.flipY; } if (data.width !== void 0) { component.width = data.width; } if (data.height !== void 0) { component.height = data.height; } if (data.spriteAsset !== void 0) { component.spriteAsset = data.spriteAsset; } if (data.sprite) { component.sprite = data.sprite; } if (data.frame !== void 0) { component.frame = data.frame; } if (data.clips) { for (const name in data.clips) { component.addClip(data.clips[name]); } } if (data.speed !== void 0) { component.speed = data.speed; } if (data.autoPlayClip) { component.autoPlayClip = data.autoPlayClip; } component.batchGroupId = data.batchGroupId === void 0 || 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 };