silphius/app/react/components/pixi/entity.js

192 lines
5.6 KiB
JavaScript
Raw Normal View History

2024-07-31 21:07:17 -05:00
import {Assets} from '@pixi/assets';
import {Container as PixiContainer} from '@pixi/display';
import {Sprite} from '@pixi/sprite';
import Aabb from './aabb.js';
import createCrosshair from './crosshair.js';
import {deferredLighting, PointLight} from './lights.js';
export default class Entity {
static assets = {};
attached = false;
colliderAabb = new Aabb({color: 0xffffff});
container = new PixiContainer();
crosshair = createCrosshair();
debug = new PixiContainer();
diffuse = new Sprite();
isMainEntity = false;
normals = new Sprite();
point;
sprite = new PixiContainer();
visibleAabb = new Aabb({color: 0xff00ff});
constructor() {
this.diffuse.parentGroup = deferredLighting.diffuseGroup;
this.normals.parentGroup = deferredLighting.normalGroup;
this.container.addChild(this.diffuse);
this.container.addChild(this.normals);
this.container.addChild(this.crosshair);
this.debug.addChild(this.colliderAabb);
this.debug.addChild(this.visibleAabb);
}
addToContainer(container) {
if (this.attached || !container) {
return;
}
container.addChild(this.container);
container.addChild(this.debug);
this.attached = true;
}
static async loadAsset(source = '') {
if (!this.assets['']) {
const {Texture} = await import('@pixi/core');
this.assets[''] = {data: {meta: {}}, textures: {'': Texture.WHITE}};
}
if (!this.assets[source]) {
this.assets[source] = Assets.load(source);
}
return this.assets[source];
}
removeFromContainer() {
this.container.parent.removeChild(this.container);
this.debug.parent.removeChild(this.debug);
this.attached = false;
}
reset(entity, debug) {
this.entity = entity;
if (this.light) {
this.container.removeChild(this.light);
this.light = undefined;
}
this.setDebug(debug);
this.isMainEntity = false;
if (this.interactionAabb) {
this.debug.removeChild(this.interactionAabb);
}
this.interactionAabb = undefined;
}
setDebug(isDebugging) {
if (isDebugging) {
this.crosshair.alpha = 1;
this.debug.alpha = 1;
}
else {
this.crosshair.alpha = 0;
this.debug.alpha = 0;
}
}
setMainEntity() {
if (this.isMainEntity) {
return;
}
this.isMainEntity = true;
this.interactionAabb = new Aabb({color: 0x00ff00});
this.debug.addChild(this.interactionAabb);
}
static textureFromAsset(asset, animation, frame) {
if (!asset) {
return undefined;
}
let texture;
if (asset.data.animations) {
if (!animation) {
return undefined;
}
texture = asset.animations[animation][frame];
}
else {
texture = asset.textures[''];
}
return texture;
}
update({Direction, Light, Position, Sprite, VisibleAabb}) {
if (Light) {
if (!this.light) {
this.light = new PointLight(
0xffffff - 0x2244cc,
0,
);
}
this.light.brightness = Light.brightness;
}
if (Position) {
const {x, y} = this.entity.Position;
this.container.x = x;
this.container.y = y;
this.container.zIndex = y;
}
if (Sprite) {
const {diffuse, normals} = this;
if (!this.attached || 'alpha' in Sprite) {
diffuse.alpha = normals.alpha = this.entity.Sprite.alpha;
}
if (!this.attached || 'anchorX' in Sprite) {
diffuse.anchor.x = normals.anchor.x = this.entity.Sprite.anchorX;
}
if (!this.attached || 'anchorY' in Sprite) {
diffuse.anchor.y = normals.anchor.y = this.entity.Sprite.anchorY;
}
if (!this.attached || 'scaleX' in Sprite) {
diffuse.scale.x = normals.scale.x = this.entity.Sprite.scaleX;
}
if (!this.attached || 'scaleY' in Sprite) {
diffuse.scale.y = normals.scale.y = this.entity.Sprite.scaleY;
}
if (!this.attached || 'tint' in Sprite) {
diffuse.tint = normals.tint = this.entity.Sprite.tint;
}
if (
!this.attached
|| ('source' in Sprite)
|| ('animation' in Sprite)
|| ('frame' in Sprite)
) {
this.constructor.loadAsset(this.entity.Sprite.source).then(async (asset) => {
const texture = await this.constructor.textureFromAsset(
asset,
this.entity.Sprite.animation,
this.entity.Sprite.frame,
);
diffuse.texture = texture;
if (asset.data.meta.normals) {
const {pathname} = new URL(
Sprite.source
.split('/')
.slice(0, -1)
.concat(asset.data.meta.normals)
.join('/'),
'http://example.org',
);
this.constructor.loadAsset(pathname).then(async (asset) => {
const texture = await this.constructor.textureFromAsset(
asset,
this.entity.Sprite.animation,
this.entity.Sprite.frame,
);
normals.texture = texture;
});
}
});
}
}
if (Direction) {
const {diffuse, normals} = this;
if ('direction' in Direction) {
if (this.entity.Sprite.rotates) {
const rotation = Direction.direction + this.entity.Sprite.rotation;
diffuse.rotation = rotation;
normals.rotation = rotation;
}
}
}
if (this.entity.Collider) {
this.colliderAabb.redraw(this.entity.Collider.aabb);
}
if (VisibleAabb) {
this.visibleAabb.redraw(this.entity.VisibleAabb);
}
if (this.isMainEntity) {
this.interactionAabb.redraw(this.entity.Interacts.aabb());
}
}
}