Add composite object implementation
parent
34842e4803
commit
7805c2fe06
@ -0,0 +1,93 @@
|
||||
'use strict';
|
||||
|
||||
const dotty = require("dotty");
|
||||
const defaultValue = require("default-value");
|
||||
|
||||
const createObject = require("./create-object");
|
||||
const createPropertyMapper = require("./property-mapper");
|
||||
const max = require("./util/max");
|
||||
const min = require("./util/min");
|
||||
|
||||
function getPosition(object) {
|
||||
return {
|
||||
x: defaultValue(object.x, 0),
|
||||
y: defaultValue(object.y, 0)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function createCompositeObject(options) {
|
||||
let mapProperties = createPropertyMapper(options.propertyMap);
|
||||
|
||||
let compositeObject = createObject(Object.assign({
|
||||
onSet: function setCompositeProperties(properties) {
|
||||
let mappedProperties = mapProperties(properties);
|
||||
|
||||
Object.keys(mappedProperties).forEach((objectName) => {
|
||||
if (objectName !== "_") {
|
||||
if (this.objects[objectName] != null) {
|
||||
this.objects[objectName].set(mappedProperties[objectName]);
|
||||
} else {
|
||||
throw new Error(`The object specified in the property map as '${objectName}' does not exist`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* We return the `_` object here, which contains all the unmapped
|
||||
* properties - we assume that all unmapped properties are meant to
|
||||
* apply to the composite object rather than its child objects. The
|
||||
* original `.set` method (as defined in createObject) will then use
|
||||
* this result. */
|
||||
return defaultValue(mappedProperties._, {});
|
||||
},
|
||||
onRender: function onRender(context) {
|
||||
Object.keys(this.objects).forEach((objectName) => {
|
||||
let object = this.objects[objectName];
|
||||
let position = getPosition(object);
|
||||
|
||||
object.render(context, {
|
||||
x: object.x - this.renderOffsetX,
|
||||
y: object.y - this.renderOffsetY
|
||||
});
|
||||
});
|
||||
},
|
||||
onRecalculateSize: function onRecalculateSize() {
|
||||
let objectMetrics = Object.keys(this.objects).map((objectName) => {
|
||||
let object = this.objects[objectName];
|
||||
let position = getPosition(object);
|
||||
|
||||
console.log(object.type, [object.x, object.y], [position.x, position.y], object.renderWidth, object.renderHeight);
|
||||
|
||||
return {
|
||||
x1: position.x,
|
||||
y1: position.y,
|
||||
x2: position.x + object.renderWidth,
|
||||
y2: position.y + object.renderHeight
|
||||
}
|
||||
});
|
||||
|
||||
let x1 = min(objectMetrics.map(object => object.x1));
|
||||
let y1 = min(objectMetrics.map(object => object.y1));
|
||||
let x2 = max(objectMetrics.map(object => object.x2));
|
||||
let y2 = max(objectMetrics.map(object => object.y2));
|
||||
|
||||
return {
|
||||
width: x2 - x1,
|
||||
height: y2 - y1,
|
||||
offsetX: x1,
|
||||
offsetY: y1
|
||||
}
|
||||
}
|
||||
}, options));
|
||||
|
||||
Object.keys(compositeObject.objects).forEach((objectName) => {
|
||||
compositeObject.objects[objectName].on("recalculatedSize", () => {
|
||||
compositeObject.recalculateSize();
|
||||
});
|
||||
|
||||
compositeObject.objects[objectName].on("renderedToCache", () => {
|
||||
compositeObject.bustCache();
|
||||
});
|
||||
});
|
||||
|
||||
return compositeObject;
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function max(values) {
|
||||
return Math.max(...values);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function min(values) {
|
||||
return Math.min(...values);
|
||||
}
|
Loading…
Reference in New Issue