164 lines
3.4 KiB
JavaScript
164 lines
3.4 KiB
JavaScript
import * as I from 'immutable';
|
|
|
|
import {compose} from '@avocado/core';
|
|
import {Vector} from '@avocado/math';
|
|
import {Property} from '@avocado/mixins';
|
|
import {Resource} from '@avocado/resource';
|
|
import {Synchronized} from '@avocado/state';
|
|
|
|
const decorate = compose(
|
|
Synchronized,
|
|
);
|
|
|
|
export class Trait extends decorate(class {}) {
|
|
|
|
constructor(entity, params, state) {
|
|
super();
|
|
this.entity = entity;
|
|
const ctor = this.constructor;
|
|
this.isDirty = true;
|
|
this.params = I.fromJS(ctor.defaultParams()).merge(I.fromJS(params));
|
|
this.state = I.fromJS(ctor.defaultState()).merge(I.fromJS(state));
|
|
}
|
|
|
|
destroy() {}
|
|
|
|
get isDirty() {
|
|
return this._isDirty;
|
|
}
|
|
|
|
set isDirty(isDirty) {
|
|
this._isDirty = isDirty;
|
|
}
|
|
|
|
hooks() {
|
|
return {};
|
|
}
|
|
|
|
hydrate() {
|
|
return Promise.resolve();
|
|
}
|
|
|
|
initialize() {}
|
|
|
|
label() {
|
|
return this.constructor.name;
|
|
}
|
|
|
|
listeners() {
|
|
return {};
|
|
}
|
|
|
|
methods() {
|
|
return {};
|
|
}
|
|
|
|
patchStateStep(key, step) {
|
|
if ('state' !== key) {
|
|
return;
|
|
}
|
|
const stateKey = step.path.substr(1);
|
|
const value = this.transformPatchValue(stateKey, step.value);
|
|
if (stateKey in this.entity) {
|
|
this.entity[stateKey] = value;
|
|
}
|
|
else {
|
|
this.state = this.state.set(stateKey, value);
|
|
}
|
|
}
|
|
|
|
renderTick(elapsed) {}
|
|
|
|
tick(elapsed) {}
|
|
|
|
toJSON() {
|
|
return {
|
|
params: this.params.toJS(),
|
|
state: this.state.toJS(),
|
|
};
|
|
}
|
|
|
|
transformPatchValue(key, value) {
|
|
return value;
|
|
}
|
|
|
|
static contextType() {
|
|
return {};
|
|
}
|
|
|
|
static defaultParams() {
|
|
return {};
|
|
}
|
|
|
|
static defaultState() {
|
|
return {};
|
|
}
|
|
|
|
static dependencies() {
|
|
return [];
|
|
}
|
|
|
|
static type() {
|
|
return this.name.toLowerCase();
|
|
}
|
|
|
|
}
|
|
|
|
export function StateProperty(key, meta = {}) {
|
|
let transformedProperty;
|
|
if (meta.transformProperty) {
|
|
transformedProperty = meta.transformProperty(key);
|
|
}
|
|
else {
|
|
transformedProperty = `$$avocado_state_property_${key}`;
|
|
}
|
|
return (Superclass) => {
|
|
meta.emit = meta.emit || function(...args) {
|
|
this.entity.emit(...args);
|
|
};
|
|
meta.initialize = meta.initialize || function() {
|
|
this[transformedProperty] = this.state.get(key);
|
|
}
|
|
meta.get = meta.get || new Function(`
|
|
return this.${transformedProperty};
|
|
`);
|
|
meta.set = meta.set || new Function('value', `
|
|
this.isDirty = true;
|
|
this.${transformedProperty} = value;
|
|
this.state = this.state.set('${key}', value);
|
|
`);
|
|
return Property(key, meta)(Superclass);
|
|
}
|
|
}
|
|
|
|
StateProperty.Vector = (vector, x, y, meta = {}) => {
|
|
return (Superclass) => {
|
|
meta.default = undefined;
|
|
meta.emit = meta.emit || function(...args) {
|
|
this.entity.emit(...args);
|
|
};
|
|
meta.get = meta.get || function() {
|
|
return [
|
|
this.state.get(x),
|
|
this.state.get(y),
|
|
];
|
|
};
|
|
meta.set = meta.set || function(vector) {
|
|
if (meta.track && meta.emit) {
|
|
if (this.state.get(x) !== vector[0]) {
|
|
meta.emit.call(this, `${x}Changed`, this.state.get(x), vector[0]);
|
|
}
|
|
if (this.state.get(y) !== vector[1]) {
|
|
meta.emit.call(this, `${y}Changed`, this.state.get(y), vector[1]);
|
|
}
|
|
}
|
|
this.isDirty = true;
|
|
this.state = this.state.merge({
|
|
[x]: vector[0],
|
|
[y]: vector[1],
|
|
});
|
|
};
|
|
return Vector.Mixin(vector, x, y, meta)(Superclass);
|
|
};
|
|
}
|