2024-06-26 21:08:09 -05:00
|
|
|
import Component from '@/ecs/component.js';
|
2024-08-04 20:55:10 -05:00
|
|
|
import {hexToHsl, hslToHex} from '@/util/color.js';
|
2024-06-26 21:08:09 -05:00
|
|
|
|
|
|
|
export default class Sprite extends Component {
|
2024-07-03 21:56:55 -05:00
|
|
|
instanceFromSchema() {
|
|
|
|
return class SpriteInstance extends super.instanceFromSchema() {
|
2024-07-30 09:56:53 -05:00
|
|
|
$$anchor = {x: 0.5, y: 0.5};
|
2024-08-01 00:39:54 -05:00
|
|
|
$$hue = 0;
|
|
|
|
$$saturation = 0;
|
|
|
|
$$lightness = 1;
|
2024-07-30 09:56:53 -05:00
|
|
|
$$scale = {x: 1, y: 1};
|
2024-07-21 11:14:51 -05:00
|
|
|
$$sourceJson = {};
|
2024-07-03 21:56:55 -05:00
|
|
|
get anchor() {
|
2024-07-30 09:56:53 -05:00
|
|
|
return this.$$anchor;
|
|
|
|
}
|
|
|
|
get anchorX() {
|
|
|
|
return this.$$anchor.x;
|
|
|
|
}
|
|
|
|
set anchorX(anchorX) {
|
|
|
|
this.$$anchor = {x: anchorX, y: this.anchorY};
|
2024-07-31 21:07:17 -05:00
|
|
|
super.anchorX = anchorX;
|
2024-07-30 09:56:53 -05:00
|
|
|
}
|
|
|
|
get anchorY() {
|
|
|
|
return this.$$anchor.y;
|
|
|
|
}
|
|
|
|
set anchorY(anchorY) {
|
|
|
|
this.$$anchor = {x: this.anchorX, y: anchorY};
|
2024-07-31 21:07:17 -05:00
|
|
|
super.anchorY = anchorY;
|
2024-07-03 21:56:55 -05:00
|
|
|
}
|
2024-07-21 11:14:51 -05:00
|
|
|
get animation() {
|
|
|
|
return super.animation;
|
|
|
|
}
|
|
|
|
set animation(animation) {
|
2024-07-25 10:48:22 -05:00
|
|
|
if (this.$$animation === animation) {
|
|
|
|
return;
|
|
|
|
}
|
2024-07-21 11:14:51 -05:00
|
|
|
super.animation = animation;
|
|
|
|
// eslint-disable-next-line no-self-assign
|
|
|
|
this.frame = this.frame;
|
|
|
|
}
|
|
|
|
get frame() {
|
|
|
|
return super.frame;
|
|
|
|
}
|
|
|
|
set frame(frame) {
|
|
|
|
super.frame = this.frames ? frame % this.frames : 0;
|
|
|
|
}
|
|
|
|
get frames() {
|
2024-07-22 01:25:05 -05:00
|
|
|
if (
|
|
|
|
!this.animation
|
|
|
|
|| !this.$$sourceJson.animations
|
|
|
|
|| !(this.animation in this.$$sourceJson.animations)
|
|
|
|
) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return this.$$sourceJson.animations[this.animation].length;
|
2024-07-21 11:14:51 -05:00
|
|
|
}
|
2024-07-25 10:48:22 -05:00
|
|
|
hasAnimation(animation) {
|
|
|
|
if (
|
|
|
|
!this.$$sourceJson.animations
|
|
|
|
|| !(animation in this.$$sourceJson.animations)
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2024-08-01 00:39:54 -05:00
|
|
|
get hue() {
|
|
|
|
return this.$$hue;
|
|
|
|
}
|
|
|
|
set hue(hue) {
|
2024-08-05 01:41:21 -05:00
|
|
|
this.$$hue = hue;
|
2024-08-01 00:39:54 -05:00
|
|
|
const [, s, l] = hexToHsl(this.$$tint);
|
2024-08-05 01:41:21 -05:00
|
|
|
super.tint = hslToHex(hue, s, l);
|
2024-08-01 00:39:54 -05:00
|
|
|
}
|
2024-08-04 21:56:06 -05:00
|
|
|
initialize(values, defaults) {
|
|
|
|
let {
|
2024-08-05 13:32:33 -05:00
|
|
|
animation = defaults.animation,
|
2024-08-04 21:56:06 -05:00
|
|
|
anchorX = defaults.anchorX,
|
|
|
|
anchorY = defaults.anchorY,
|
|
|
|
frame = defaults.frame,
|
|
|
|
scaleX = defaults.scaleX,
|
|
|
|
scaleY = defaults.scaleY,
|
|
|
|
} = values;
|
|
|
|
this.$$anchor = {x: anchorX, y: anchorY};
|
|
|
|
this.$$scale = {x: scaleX, y: scaleY};
|
|
|
|
super.initialize(values, defaults);
|
|
|
|
this.frame = frame;
|
2024-08-05 13:32:33 -05:00
|
|
|
this.animation = animation;
|
2024-08-04 21:56:06 -05:00
|
|
|
}
|
2024-08-01 00:39:54 -05:00
|
|
|
get lightness() {
|
|
|
|
return this.$$lightness;
|
|
|
|
}
|
|
|
|
set lightness(lightness) {
|
2024-08-05 01:41:21 -05:00
|
|
|
this.$$lightness = lightness;
|
2024-08-01 00:39:54 -05:00
|
|
|
const [h, s] = hexToHsl(this.$$tint);
|
2024-08-05 13:57:15 -05:00
|
|
|
super.tint = hslToHex(h, s, lightness);
|
2024-08-01 00:39:54 -05:00
|
|
|
}
|
2024-07-25 10:48:22 -05:00
|
|
|
get rotates() {
|
|
|
|
if (!this.$$sourceJson.meta) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return 'rotation' in this.$$sourceJson.meta;
|
|
|
|
}
|
|
|
|
get rotation() {
|
|
|
|
if (!this.$$sourceJson.meta) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return this.$$sourceJson.meta.rotation;
|
|
|
|
}
|
2024-08-01 00:39:54 -05:00
|
|
|
get saturation() {
|
|
|
|
return this.$$saturation;
|
|
|
|
}
|
|
|
|
set saturation(saturation) {
|
2024-08-05 01:41:21 -05:00
|
|
|
this.$$saturation = saturation;
|
2024-08-01 00:39:54 -05:00
|
|
|
const [h, , l] = hexToHsl(this.$$tint);
|
2024-08-05 01:41:21 -05:00
|
|
|
super.tint = hslToHex(h, saturation, l);
|
2024-08-01 00:39:54 -05:00
|
|
|
}
|
2024-07-03 21:56:55 -05:00
|
|
|
get scale() {
|
2024-07-30 09:56:53 -05:00
|
|
|
return this.$$scale;
|
|
|
|
}
|
2024-08-01 14:31:18 -05:00
|
|
|
set scale(scale) {
|
|
|
|
if ('number' === typeof scale) {
|
|
|
|
scale = {x: scale, y: scale};
|
|
|
|
}
|
|
|
|
this.scaleX = scale.x;
|
|
|
|
this.scaleY = scale.y;
|
|
|
|
}
|
2024-07-30 09:56:53 -05:00
|
|
|
get scaleX() {
|
|
|
|
return this.$$scale.x;
|
|
|
|
}
|
|
|
|
set scaleX(scaleX) {
|
|
|
|
this.$$scale = {x: scaleX, y: this.scaleY};
|
2024-07-31 21:07:17 -05:00
|
|
|
super.scaleX = scaleX;
|
2024-07-30 09:56:53 -05:00
|
|
|
}
|
|
|
|
get scaleY() {
|
|
|
|
return this.$$scale.y;
|
|
|
|
}
|
|
|
|
set scaleY(scaleY) {
|
|
|
|
this.$$scale = {x: this.scaleX, y: scaleY};
|
2024-07-31 21:07:17 -05:00
|
|
|
super.scaleY = scaleY;
|
2024-07-30 09:56:53 -05:00
|
|
|
}
|
|
|
|
get size() {
|
|
|
|
if (!this.$$sourceJson.frames) {
|
|
|
|
return {x: 16, y: 16};
|
|
|
|
}
|
|
|
|
const frame = this.animation
|
|
|
|
? this.$$sourceJson.animations[this.animation][this.frame]
|
|
|
|
: '';
|
|
|
|
return this.$$sourceJson.frames[frame].sourceSize;
|
2024-07-03 21:56:55 -05:00
|
|
|
}
|
2024-08-01 00:39:54 -05:00
|
|
|
get tint() {
|
|
|
|
return super.tint;
|
|
|
|
}
|
|
|
|
set tint(tint) {
|
|
|
|
[
|
|
|
|
this.$$hue,
|
|
|
|
this.$$saturation,
|
|
|
|
this.$$lightness,
|
|
|
|
] = hexToHsl(tint)
|
|
|
|
super.tint = tint;
|
|
|
|
}
|
2024-07-28 18:42:28 -05:00
|
|
|
toNet(recipient, data) {
|
2024-07-21 07:22:48 -05:00
|
|
|
// eslint-disable-next-line no-unused-vars
|
2024-07-28 18:42:28 -05:00
|
|
|
const {elapsed, ...rest} = super.toNet(recipient, data);
|
2024-07-21 07:22:48 -05:00
|
|
|
return rest;
|
|
|
|
}
|
2024-07-31 21:07:17 -05:00
|
|
|
update(values) {
|
|
|
|
for (const key in values) {
|
|
|
|
switch (key) {
|
|
|
|
case 'anchorX': {
|
|
|
|
this.$$anchor.x = values[key];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'anchorY': {
|
|
|
|
this.$$anchor.y = values[key];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'scaleX': {
|
|
|
|
this.$$scale.x = values[key];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'scaleY': {
|
|
|
|
this.$$scale.y = values[key];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return super.update(values);
|
|
|
|
}
|
2024-07-03 21:56:55 -05:00
|
|
|
};
|
|
|
|
}
|
2024-07-02 12:00:12 -05:00
|
|
|
async load(instance) {
|
2024-07-30 09:56:53 -05:00
|
|
|
if (instance.source) {
|
|
|
|
instance.$$sourceJson = await this.ecs.readJson(instance.source);
|
|
|
|
}
|
2024-07-02 12:00:12 -05:00
|
|
|
}
|
2024-07-21 07:22:48 -05:00
|
|
|
markChange(entityId, key, value) {
|
|
|
|
if ('elapsed' === key) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
super.markChange(entityId, key, value);
|
|
|
|
}
|
2024-06-26 21:08:09 -05:00
|
|
|
static properties = {
|
2024-07-25 10:48:22 -05:00
|
|
|
alpha: {defaultValue: 1, type: 'float32'},
|
2024-07-03 21:56:55 -05:00
|
|
|
anchorX: {defaultValue: 0.5, type: 'float32'},
|
|
|
|
anchorY: {defaultValue: 0.5, type: 'float32'},
|
2024-06-26 21:08:09 -05:00
|
|
|
animation: {type: 'string'},
|
|
|
|
elapsed: {type: 'float32'},
|
|
|
|
frame: {type: 'uint16'},
|
2024-07-21 11:14:51 -05:00
|
|
|
isAnimating: {defaultValue: 1, type: 'uint8'},
|
2024-07-03 21:56:55 -05:00
|
|
|
scaleX: {defaultValue: 1, type: 'float32'},
|
|
|
|
scaleY: {defaultValue: 1, type: 'float32'},
|
2024-06-26 21:08:09 -05:00
|
|
|
source: {type: 'string'},
|
|
|
|
speed: {type: 'float32'},
|
2024-07-31 21:07:17 -05:00
|
|
|
tint: {defaultValue: 0xffffff, type: 'uint32'},
|
2024-06-26 21:08:09 -05:00
|
|
|
};
|
|
|
|
}
|