From eb931fd99bf0a32e694e2ac67d495ddd7799ebfd Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Wed, 24 May 2017 15:30:29 -0700 Subject: [PATCH 1/2] Specify dataFormat when loading asset for import When importing a project we know the file extension for each asset to be loaded. This change provides that information to the storage system so that we can load assets which don't use the default. For example, this allows loading JPG-format backdrops. In support of this change, there's a new function on `StringUtil` called `splitFirst`, which splits a string on the first instance of a separator character. This change includes unit tests for this new function. --- src/import/load-costume.js | 9 +++++---- src/import/load-sound.js | 6 ++++-- src/playground/playground.js | 2 +- src/serialization/sb3.js | 2 +- src/util/string-util.js | 24 ++++++++++++++++++++++++ test/fixtures/attach-test-storage.js | 2 +- test/unit/util_string.js | 8 ++++++++ 7 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/import/load-costume.js b/src/import/load-costume.js index a9323398d..54962ea1f 100644 --- a/src/import/load-costume.js +++ b/src/import/load-costume.js @@ -1,3 +1,4 @@ +const StringUtil = require('../util/string-util'); const log = require('../util/log'); /** @@ -19,17 +20,17 @@ const loadCostume = function (md5ext, costume, runtime) { } const AssetType = runtime.storage.AssetType; - const idParts = md5ext.split('.'); + const idParts = StringUtil.splitFirst(md5ext, '.'); const md5 = idParts[0]; - const ext = idParts[1].toUpperCase(); - const assetType = (ext === 'SVG') ? AssetType.ImageVector : AssetType.ImageBitmap; + const ext = idParts[1].toLowerCase(); + 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 => { + let promise = runtime.storage.load(assetType, md5, ext).then(costumeAsset => { costume.assetId = costumeAsset.assetId; costume.assetType = assetType; return costumeAsset; diff --git a/src/import/load-sound.js b/src/import/load-sound.js index a308e1516..80b595987 100644 --- a/src/import/load-sound.js +++ b/src/import/load-sound.js @@ -1,3 +1,4 @@ +const StringUtil = require('../util/string-util'); const log = require('../util/log'); /** @@ -17,9 +18,10 @@ const loadSound = function (sound, runtime) { log.error('No audio engine present; cannot load sound asset: ', sound.md5); return Promise.resolve(sound); } - const idParts = sound.md5.split('.'); + const idParts = StringUtil.splitFirst(sound.md5, '.'); const md5 = idParts[0]; - return runtime.storage.load(runtime.storage.AssetType.Sound, md5) + const ext = idParts[1].toLowerCase(); + return runtime.storage.load(runtime.storage.AssetType.Sound, md5, ext) .then(soundAsset => { sound.assetId = soundAsset.assetId; sound.assetType = runtime.storage.AssetType.Sound; diff --git a/src/playground/playground.js b/src/playground/playground.js index c1b655a58..814bfb628 100644 --- a/src/playground/playground.js +++ b/src/playground/playground.js @@ -34,7 +34,7 @@ const getAssetUrl = function (asset) { 'internalapi/asset/', asset.assetId, '.', - asset.assetType.runtimeFormat, + asset.dataFormat, '/get/' ]; return assetUrlParts.join(''); diff --git a/src/serialization/sb3.js b/src/serialization/sb3.js index 4477a7b51..9708b9195 100644 --- a/src/serialization/sb3.js +++ b/src/serialization/sb3.js @@ -75,7 +75,7 @@ const parseScratchObject = function (object, runtime) { rotationCenterX: costumeSource.rotationCenterX, rotationCenterY: costumeSource.rotationCenterY }; - const costumeMd5 = `${costumeSource.assetId}.${costumeSource.assetType.runtimeFormat}`; + const costumeMd5 = `${costumeSource.assetId}.${costumeSource.dataFormat}`; return loadCostume(costumeMd5, costume, runtime); }); // Sounds from JSON diff --git a/src/util/string-util.js b/src/util/string-util.js index 0ee712548..48dde0277 100644 --- a/src/util/string-util.js +++ b/src/util/string-util.js @@ -12,6 +12,30 @@ class StringUtil { while (existingNames.indexOf(name + i) >= 0) i++; return name + i; } + + /** + * Split a string on the first occurrence of a split character. + * @param {string} text - the string to split. + * @param {string} separator - split the text on this character. + * @returns {[string, string]} - the two parts of the split string, or [text, null] if no split character found. + * @example + * // returns ['foo', 'tar.gz'] + * splitFirst('foo.tar.gz', '.'); + * @example + * // returns ['foo', null] + * splitFirst('foo', '.'); + * @example + * // returns ['foo', ''] + * splitFirst('foo.', '.'); + */ + static splitFirst (text, separator) { + const index = text.indexOf(separator); + if (index >= 0) { + return [text.substring(0, index), text.substring(index + 1)]; + } else { + return [text, null]; + } + } } module.exports = StringUtil; diff --git a/test/fixtures/attach-test-storage.js b/test/fixtures/attach-test-storage.js index 3e75f5967..bb0cc3a08 100644 --- a/test/fixtures/attach-test-storage.js +++ b/test/fixtures/attach-test-storage.js @@ -26,7 +26,7 @@ const getAssetUrl = function (asset) { 'internalapi/asset/', asset.assetId, '.', - asset.assetType.runtimeFormat, + asset.dataFormat, '/get/' ]; return assetUrlParts.join(''); diff --git a/test/unit/util_string.js b/test/unit/util_string.js index 741336258..aca20f9a4 100644 --- a/test/unit/util_string.js +++ b/test/unit/util_string.js @@ -1,6 +1,14 @@ const test = require('tap').test; const StringUtil = require('../../src/util/string-util'); +test('splitFirst', t => { + t.deepEqual(StringUtil.splitFirst('asdf.1234', '.'), ['asdf', '1234']); + t.deepEqual(StringUtil.splitFirst('asdf.', '.'), ['asdf', '']); + t.deepEqual(StringUtil.splitFirst('.1234', '.'), ['', '1234']); + t.deepEqual(StringUtil.splitFirst('foo', '.'), ['foo', null]); + t.end(); +}); + test('withoutTrailingDigits', t => { t.strictEqual(StringUtil.withoutTrailingDigits('boeing747'), 'boeing'); t.strictEqual(StringUtil.withoutTrailingDigits('boeing747 '), 'boeing747 '); From 467b747283afdd610cc1ac8b8bf8e31f074fa2ad Mon Sep 17 00:00:00 2001 From: Ray Schamp Date: Fri, 2 Jun 2017 08:57:21 -0400 Subject: [PATCH 2/2] Bump scratch-storage version Now 0.2.0 is the lowest compatible version. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0308aa6f7..11fb66efe 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "scratch-audio": "^0.1.0-prerelease.0", "scratch-blocks": "^0.1.0-prerelease.0", "scratch-render": "^0.1.0-prerelease.0", - "scratch-storage": "^0.1.0", + "scratch-storage": "^0.2.0", "script-loader": "0.7.0", "stats.js": "^0.17.0", "tap": "^10.2.0",