Merge pull request from fsih/fixQuirksOnLoadCostume

Run quirks mode fixes on costumes loaded from sb2s
This commit is contained in:
DD Liu 2018-05-10 13:42:48 -04:00 committed by GitHub
commit 5c003641f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 5 deletions

View file

@ -917,6 +917,14 @@ class Runtime extends EventEmitter {
this.renderer = renderer;
}
/**
* Set the svg adapter, which converts scratch 2 svgs to scratch 3 svgs
* @param {!SvgRenderer} svgAdapter The adapter to attach
*/
attachV2SVGAdapter (svgAdapter) {
this.v2SvgAdapter = svgAdapter;
}
/**
* Attach the storage module
* @param {!ScratchStorage} storage The storage module to attach

View file

@ -11,9 +11,11 @@ const log = require('../util/log');
* @property {number} [bitmapResolution] - the resolution scale for a bitmap costume.
* @param {!Asset} costumeAsset - the asset of the costume loaded from storage.
* @param {!Runtime} runtime - Scratch runtime, used to access the storage module.
* @param {?int} optVersion - Version of Scratch that the costume comes from. If this is set
* to 2, scratch 3 will perform an upgrade step to handle quirks in SVGs from Scratch 2.0.
* @returns {?Promise} - a promise which will resolve after skinId is set, or null on error.
*/
const loadCostumeFromAsset = function (costume, costumeAsset, runtime) {
const loadCostumeFromAsset = function (costume, costumeAsset, runtime, optVersion) {
costume.assetId = costumeAsset.assetId;
const renderer = runtime.renderer;
if (!renderer) {
@ -29,9 +31,24 @@ const loadCostumeFromAsset = function (costume, costumeAsset, runtime) {
];
}
if (costumeAsset.assetType === AssetType.ImageVector) {
let svgString = costumeAsset.decodeText();
// SVG Renderer load fixes "quirks" associated with Scratch 2 projects
if (optVersion && optVersion === 2 && runtime.v2SvgAdapter) {
runtime.v2SvgAdapter.loadString(svgString);
svgString = runtime.v2SvgAdapter.toString();
// Put back into storage
const storage = runtime.storage;
costumeAsset.encodeTextData(svgString, storage.DataFormat.SVG);
costume.assetId = storage.builtinHelper.cache(
storage.AssetType.ImageVector,
storage.DataFormat.SVG,
costumeAsset.data
);
costume.md5 = `${costume.assetId}.${costume.dataFormat}`;
}
// createSVGSkin does the right thing if rotationCenter isn't provided, so it's okay if it's
// undefined here
costume.skinId = renderer.createSVGSkin(costumeAsset.decodeText(), rotationCenter);
costume.skinId = renderer.createSVGSkin(svgString, rotationCenter);
costume.size = renderer.getSkinSize(costume.skinId);
// Now we should have a rotationCenter even if we didn't before
if (!rotationCenter) {
@ -86,9 +103,11 @@ const loadCostumeFromAsset = function (costume, costumeAsset, runtime) {
* @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.
* @param {?int} optVersion - Version of Scratch that the costume comes from. If this is set
* to 2, scratch 3 will perform an upgrade step to handle quirks in SVGs from Scratch 2.0.
* @returns {?Promise} - a promise which will resolve after skinId is set, or null on error.
*/
const loadCostume = function (md5ext, costume, runtime) {
const loadCostume = function (md5ext, costume, runtime, optVersion) {
if (!runtime.storage) {
log.error('No storage module present; cannot load costume asset: ', md5ext);
return Promise.resolve(costume);
@ -102,7 +121,7 @@ const loadCostume = function (md5ext, costume, runtime) {
return runtime.storage.load(assetType, md5, ext).then(costumeAsset => {
costume.dataFormat = ext;
return loadCostumeFromAsset(costume, costumeAsset, runtime);
return loadCostumeFromAsset(costume, costumeAsset, runtime, optVersion);
});
};

View file

@ -360,7 +360,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip)
// the file name of the costume should be the baseLayerID followed by the file ext
const assetFileName = `${costumeSource.baseLayerID}.${ext}`;
costumePromises.push(deserializeCostume(costume, runtime, zip, assetFileName)
.then(() => loadCostume(costume.md5, costume, runtime)));
.then(() => loadCostume(costume.md5, costume, runtime, 2 /* optVersion */)));
}
}
// Sounds from JSON

View file

@ -826,6 +826,14 @@ class VirtualMachine extends EventEmitter {
this.runtime.attachRenderer(renderer);
}
/**
* Set the svg adapter for the VM/runtime, which converts scratch 2 svgs to scratch 3 svgs
* @param {!SvgRenderer} svgAdapter The adapter to attach
*/
attachV2SVGAdapter (svgAdapter) {
this.runtime.attachV2SVGAdapter(svgAdapter);
}
/**
* Set the storage module for the VM/runtime
* @param {!ScratchStorage} storage The storage module to attach