refactor: Vector mixin

This commit is contained in:
cha0s 2019-03-21 23:13:46 -05:00
parent 25809f5b31
commit 0de58ff338
5 changed files with 98 additions and 73 deletions

View File

@ -1,6 +1,7 @@
import * as I from 'immutable';
import {Resource} from '@avocado/resource';
import {Vector} from '@avocado/math';
import {Property} from '@avocado/mixins';
export class Trait {
@ -95,3 +96,33 @@ export function simpleState(key, meta = {}) {
return Property(key, meta)(Superclass);
}
}
export function simpleStateVector(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.state = this.state.merge({
[x]: vector[0],
[y]: vector[1],
});
};
return Vector.Mixin(vector, x, y, meta)(Superclass);
};
}

View File

@ -1,12 +1,9 @@
import {compose} from '@avocado/core';
import {simpleState, Trait} from '../trait';
import {simpleStateVector, Trait} from '../trait';
const decorate = compose(
simpleState('x', {
track: true,
}),
simpleState('y', {
simpleStateVector('position', 'x', 'y', {
track: true,
}),
);
@ -20,42 +17,6 @@ class PositionedBase extends Trait {
};
}
get position() {
return [
this.state.get('x'),
this.state.get('y'),
];
}
set position([x, y]) {
const positionChanged = x !== entity.x || y !== entity.y;
const lastPosition = entity.position;
this.entity.x = x;
this.entity.y = y;
if (positionChanged) {
this.entity.emit('positionChanged', lastPosition, entity.position);
}
}
listeners() {
return {
xChanged: (x, oldX) => {
this.entity.emit(
'positionChanged',
this.entity.position,
[oldX, this.entity.y]
);
},
yChanged: (y, oldY) => {
this.entity.emit(
'positionChanged',
this.entity.position,
[this.entity.x, oldY]
);
},
}
}
}
export class Positioned extends decorate(PositionedBase) {}

View File

@ -1,3 +1,4 @@
export {VectorMixin as Mixin} from './mixin';
export const SQRT_2_2 = Math.sqrt(2) / 2;

View File

@ -1,32 +0,0 @@
import {Mixin, Property} from '@avocado/composition'
import {Vector as Vector_} from '@avocado/math'
import {setterName} from '@avocado/string'
export VectorMixin = (
vector = 'vector', x = 'x', y = 'y', meta = {}
) -> (Superclass) ->
setX = setterName x
setY = setterName y
Base = Mixin(Superclass).with(
Property x, meta[x] ? {}
Property y, meta[y] ? {}
Property vector, Object.assign {
set: (vector) ->
this[setX] vector[0]
this[setY] vector[1]
return
get: -> [@[x](), @[y]()]
eq: (l, r) -> Vector_.equals l, r
}, meta
)
class Vector extends Base

View File

@ -0,0 +1,64 @@
import {compose} from '@avocado/core';
import {Mixin, Property} from '@avocado/mixins'
import {Vector} from '@avocado/math'
export function VectorMixin(
vector = 'vector',
x = 'x',
y = 'y',
meta = {},
) {
meta = {
default: [0, 0],
emit: function (...args) {
if (this.emit) {
this.emit(...args);
}
},
eq: function(l, r) {
return Vector.equals(l, r);
},
get: function() {
return [
this[x],
this[y],
];
},
...meta,
};
meta.set = meta.set || function(vector) {
if (meta.track && meta.emit) {
if (this[vector][0] !== vector[0]) {
meta.emit.call(this, `${x}Changed`, this[vector][0], vector[0]);
}
if (this[vector][1] !== vector[1]) {
meta.emit.call(this, `${y}Changed`, this[vector][1], vector[1]);
}
}
this[vector] = [vector[0], vector[1]];
}
const decorate = compose(
Property(vector, meta),
);
return (Superclass) => {
return class Vector extends decorate(Superclass) {
get [x]() {
return this[vector][0];
}
set [x](x) {
this[vector] = [x, this[vector][1]];
}
get [y]() {
return this[vector][1];
}
set [y](y) {
this[vector] = [this[vector][0], y];
}
}
};
}