mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-26 16:02:54 -05:00
c9ce6776aa
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.
78 lines
3.2 KiB
JavaScript
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;
|