scratch-vm/src/import/load-costume.js
Ray Schamp c9ce6776aa Get SB3 imports working
For now, store the md5 + extension on costumes in the VM. This way we can load them the same way as we load SB2 assets.
2017-04-27 17:08:06 -04:00

78 lines
3.2 KiB
JavaScript

const log = require('../util/log');
/**
* Load a costume's asset into memory asynchronously.
* Do not call this unless there is a renderer attached.
* @param {string} md5ext - the MD5 and extension of the costume to be loaded.
* @param {!object} costume - the Scratch costume object.
* @property {int} skinId - the ID of the costume's render skin, once installed.
* @property {number} rotationCenterX - the X component of the costume's origin.
* @property {number} rotationCenterY - the Y component of the costume's origin.
* @property {number} [bitmapResolution] - the resolution scale for a bitmap costume.
* @param {!Runtime} runtime - Scratch runtime, used to access the storage module.
* @returns {?Promise} - a promise which will resolve after skinId is set, or null on error.
*/
const loadCostume = function (md5ext, costume, runtime) {
costume.md5ext = md5ext;
if (!runtime.storage) {
log.error('No storage module present; cannot load costume asset: ', md5ext);
return Promise.resolve(costume);
}
const AssetType = runtime.storage.AssetType;
const idParts = md5ext.split('.');
const md5 = idParts[0];
const ext = idParts[1].toUpperCase();
const assetType = (ext === 'SVG') ? AssetType.ImageVector : AssetType.ImageBitmap;
const rotationCenter = [
costume.rotationCenterX / costume.bitmapResolution,
costume.rotationCenterY / costume.bitmapResolution
];
let promise = runtime.storage.load(assetType, md5).then(costumeAsset => {
costume.url = costumeAsset.encodeDataURI();
return costumeAsset;
});
if (!runtime.renderer) {
log.error('No rendering module present; cannot load costume asset: ', md5ext);
return promise.then(() => costume);
}
if (assetType === AssetType.ImageVector) {
promise = promise.then(costumeAsset => {
costume.skinId = runtime.renderer.createSVGSkin(costumeAsset.decodeText(), rotationCenter);
return costume;
});
} else {
promise = promise.then(costumeAsset => (
new Promise((resolve, reject) => {
const imageElement = new Image();
const onError = function () {
// eslint-disable-next-line no-use-before-define
removeEventListeners();
reject();
};
const onLoad = function () {
// eslint-disable-next-line no-use-before-define
removeEventListeners();
resolve(imageElement);
};
const removeEventListeners = function () {
imageElement.removeEventListener('error', onError);
imageElement.removeEventListener('load', onLoad);
};
imageElement.addEventListener('error', onError);
imageElement.addEventListener('load', onLoad);
imageElement.src = costumeAsset.encodeDataURI();
})
)).then(imageElement => {
costume.skinId = runtime.renderer.createBitmapSkin(imageElement, costume.bitmapResolution, rotationCenter);
return costume;
});
}
return promise;
};
module.exports = loadCostume;