You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.8 KiB
JavaScript
98 lines
2.8 KiB
JavaScript
'use strict';
|
|
|
|
const dotty = require("dotty");
|
|
const defaultValue = require("default-value");
|
|
|
|
const createObject = require("./create-object");
|
|
const createPropertyMapper = require("./property-mapper");
|
|
const requireProperties = require("./require-properties");
|
|
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) {
|
|
requireProperties(options, ["drawOrder", "objects"]);
|
|
|
|
let mapProperties = createPropertyMapper(options.propertyMap);
|
|
let initialPropertySet = mapProperties(options);
|
|
|
|
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) {
|
|
this.drawOrder.forEach((objectName) => {
|
|
let object = this.objects[objectName];
|
|
let position = getPosition(object);
|
|
|
|
object.render(context, {
|
|
x: object.x - this.offsetX,
|
|
y: object.y - this.offsetY
|
|
});
|
|
});
|
|
},
|
|
onRecalculateSize: function onRecalculateSize() {
|
|
let objectMetrics = Object.keys(this.objects).map((objectName) => {
|
|
let object = this.objects[objectName];
|
|
let position = getPosition(object);
|
|
|
|
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));
|
|
|
|
this.offsetX = x1;
|
|
this.offsetY = y1;
|
|
|
|
return {
|
|
width: x2 - x1,
|
|
height: y2 - y1
|
|
}
|
|
}
|
|
}, initialPropertySet._));
|
|
|
|
Object.keys(compositeObject.objects).forEach((objectName) => {
|
|
compositeObject.objects[objectName].on("recalculatedSize", () => {
|
|
compositeObject.recalculateSize();
|
|
});
|
|
|
|
compositeObject.objects[objectName].on("bustedCache", () => {
|
|
compositeObject.bustCache();
|
|
});
|
|
});
|
|
|
|
compositeObject.set(options);
|
|
return compositeObject;
|
|
};
|