From 5014c7c395c1f41231a1e6e773ac3b8794516541 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Tue, 10 Jul 2018 10:43:28 -0400 Subject: [PATCH 1/7] Use bitmapAdapter for costume upload --- src/containers/costume-library.jsx | 4 ++-- src/containers/costume-tab.jsx | 4 ++-- src/containers/stage.jsx | 2 ++ src/lib/file-uploader.js | 27 +++++++++++++++++---------- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/containers/costume-library.jsx b/src/containers/costume-library.jsx index fdef46f07..0de5fba13 100644 --- a/src/containers/costume-library.jsx +++ b/src/containers/costume-library.jsx @@ -28,8 +28,8 @@ class CostumeLibrary extends React.PureComponent { handleItemSelected (item) { const vmCostume = { name: item.name, - rotationCenterX: item.info[0], - rotationCenterY: item.info[1], + rotationCenterX: item.info[0] / 2, + rotationCenterY: item.info[1] / 2, bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 248ce989b..9cd10ec8b 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -164,8 +164,8 @@ class CostumeTab extends React.Component { const vmCostume = { name: item.name, md5: item.md5, - rotationCenterX: item.info[0], - rotationCenterY: item.info[1], + rotationCenterX: item.info[0] / 2, + rotationCenterY: item.info[1] / 2, bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx index 01fc3ec7c..0ff48ef02 100644 --- a/src/containers/stage.jsx +++ b/src/containers/stage.jsx @@ -9,6 +9,7 @@ import {STAGE_DISPLAY_SIZES} from '../lib/layout-constants'; import {getEventXY} from '../lib/touch-utils'; import VideoProvider from '../lib/video/video-provider'; import {SVGRenderer as V2SVGAdapter} from 'scratch-svg-renderer'; +import {BitmapAdapter as V2BitmapAdapter} from 'scratch-svg-renderer'; import StageComponent from '../components/stage/stage.jsx'; @@ -60,6 +61,7 @@ class Stage extends React.Component { this.props.vm.attachRenderer(this.renderer); } this.props.vm.attachV2SVGAdapter(new V2SVGAdapter()); + this.props.vm.attachV2BitmapAdapter(new V2BitmapAdapter()); this.props.vm.setVideoProvider(new VideoProvider()); } componentDidMount () { diff --git a/src/lib/file-uploader.js b/src/lib/file-uploader.js index d32f5cc1c..2df9f8593 100644 --- a/src/lib/file-uploader.js +++ b/src/lib/file-uploader.js @@ -1,4 +1,4 @@ -import {importBitmap} from 'scratch-svg-renderer'; +import {BitmapAdapter} from 'scratch-svg-renderer'; import log from './log.js'; /** @@ -79,7 +79,7 @@ const cacheAsset = function (storage, fileName, assetType, dataFormat, data) { /** * Handles loading a costume or a backdrop using the provided, context-relevant information. - * @param {ArrayBuffer | string} fileData The costume data to load (this can be an image url + * @param {ArrayBuffer | string} fileData The costume data to load (this can be a base64 string * iff the image is a bitmap) * @param {string} fileType The MIME type of this file * @param {string} costumeName The user-readable name to use for the costume. @@ -112,13 +112,15 @@ const costumeUpload = function (fileData, fileType, costumeName, storage, handle return; } - const addCostumeFromBuffer = function (error, costumeBuffer) { - if (error) { - log.warn(`An error occurred while trying to extract image data: ${error}`); - return; - } - - const vmCostume = cacheAsset(storage, costumeName, assetType, costumeFormat, costumeBuffer); + const bitmapAdapter = new BitmapAdapter(); + const addCostumeFromBuffer = function (dataURI) { + const vmCostume = cacheAsset( + storage, + costumeName, + assetType, + costumeFormat, + bitmapAdapter.convertDataURIToBinary(dataURI) + ); handleCostume(vmCostume); }; @@ -130,7 +132,12 @@ const costumeUpload = function (fileData, fileType, costumeName, storage, handle addCostumeFromBuffer(null, new Uint8Array(fileData)); } else { // otherwise it's a bitmap - importBitmap(fileData, addCostumeFromBuffer); + let dataURI = fileData; + if (fileData instanceof ArrayBuffer) { + dataURI = bitmapAdapter.convertBinaryToDataURI(fileData, fileType); + } + // @todo show an error message to user on failure? + bitmapAdapter.importBitmap(dataURI).then(value => addCostumeFromBuffer(value)); } }; From 33cb3df1a183ad94f6f2863c74a2d1ee6b5cb12f Mon Sep 17 00:00:00 2001 From: DD Liu Date: Thu, 12 Jul 2018 15:05:02 -0400 Subject: [PATCH 2/7] Choose center based on file type and pass array buffer directly to import bitmap --- src/containers/costume-library.jsx | 7 +++++-- src/containers/costume-tab.jsx | 7 +++++-- src/lib/file-uploader.js | 7 +------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/containers/costume-library.jsx b/src/containers/costume-library.jsx index 0de5fba13..c4884c169 100644 --- a/src/containers/costume-library.jsx +++ b/src/containers/costume-library.jsx @@ -26,10 +26,13 @@ class CostumeLibrary extends React.PureComponent { ]); } handleItemSelected (item) { + const type = item.md5.split('.')[1]; + const rotationCenterX = type === 'svg' ? item.info[0] : item.info[0] / 2; + const rotationCenterY = type === 'svg' ? item.info[1] : item.info[1] / 2; const vmCostume = { name: item.name, - rotationCenterX: item.info[0] / 2, - rotationCenterY: item.info[1] / 2, + rotationCenterX, + rotationCenterY, bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 9cd10ec8b..34b64a2ff 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -161,11 +161,14 @@ class CostumeTab extends React.Component { } handleSurpriseCostume () { const item = costumeLibraryContent[Math.floor(Math.random() * costumeLibraryContent.length)]; + const type = item.md5.split('.')[1]; + const rotationCenterX = type === 'svg' ? item.info[0] : item.info[0] / 2; + const rotationCenterY = type === 'svg' ? item.info[1] : item.info[1] / 2; const vmCostume = { name: item.name, md5: item.md5, - rotationCenterX: item.info[0] / 2, - rotationCenterY: item.info[1] / 2, + rotationCenterX, + rotationCenterY, bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; diff --git a/src/lib/file-uploader.js b/src/lib/file-uploader.js index 2df9f8593..785b85d43 100644 --- a/src/lib/file-uploader.js +++ b/src/lib/file-uploader.js @@ -132,12 +132,7 @@ const costumeUpload = function (fileData, fileType, costumeName, storage, handle addCostumeFromBuffer(null, new Uint8Array(fileData)); } else { // otherwise it's a bitmap - let dataURI = fileData; - if (fileData instanceof ArrayBuffer) { - dataURI = bitmapAdapter.convertBinaryToDataURI(fileData, fileType); - } - // @todo show an error message to user on failure? - bitmapAdapter.importBitmap(dataURI).then(value => addCostumeFromBuffer(value)); + bitmapAdapter.importBitmap(fileData, fileType).then(value => addCostumeFromBuffer(value)); } }; From 955f328d1bf4f9bdf03a6646537cc03459d85dbf Mon Sep 17 00:00:00 2001 From: DD Liu Date: Thu, 12 Jul 2018 15:57:23 -0400 Subject: [PATCH 3/7] Split safely --- src/containers/costume-library.jsx | 3 ++- src/containers/costume-tab.jsx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/containers/costume-library.jsx b/src/containers/costume-library.jsx index c4884c169..070c9f4b9 100644 --- a/src/containers/costume-library.jsx +++ b/src/containers/costume-library.jsx @@ -26,7 +26,8 @@ class CostumeLibrary extends React.PureComponent { ]); } handleItemSelected (item) { - const type = item.md5.split('.')[1]; + const split = item.md5.split('.'); + const type = split.length > 1 ? split[1] : null; const rotationCenterX = type === 'svg' ? item.info[0] : item.info[0] / 2; const rotationCenterY = type === 'svg' ? item.info[1] : item.info[1] / 2; const vmCostume = { diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 34b64a2ff..454c5ffce 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -161,7 +161,8 @@ class CostumeTab extends React.Component { } handleSurpriseCostume () { const item = costumeLibraryContent[Math.floor(Math.random() * costumeLibraryContent.length)]; - const type = item.md5.split('.')[1]; + const split = item.md5.split('.'); + const type = split.length > 1 ? split[1] : null; const rotationCenterX = type === 'svg' ? item.info[0] : item.info[0] / 2; const rotationCenterY = type === 'svg' ? item.info[1] : item.info[1] / 2; const vmCostume = { From 34e764c96cf042f96aa3c08a6cc88eb07bc0bddb Mon Sep 17 00:00:00 2001 From: DD Liu Date: Thu, 12 Jul 2018 16:46:04 -0400 Subject: [PATCH 4/7] Don't try to convert to binary twice --- src/lib/file-uploader.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/file-uploader.js b/src/lib/file-uploader.js index 785b85d43..a5805c1c8 100644 --- a/src/lib/file-uploader.js +++ b/src/lib/file-uploader.js @@ -113,13 +113,13 @@ const costumeUpload = function (fileData, fileType, costumeName, storage, handle } const bitmapAdapter = new BitmapAdapter(); - const addCostumeFromBuffer = function (dataURI) { + const addCostumeFromBuffer = function (dataBuffer) { const vmCostume = cacheAsset( storage, costumeName, assetType, costumeFormat, - bitmapAdapter.convertDataURIToBinary(dataURI) + dataBuffer ); handleCostume(vmCostume); }; @@ -132,7 +132,7 @@ const costumeUpload = function (fileData, fileType, costumeName, storage, handle addCostumeFromBuffer(null, new Uint8Array(fileData)); } else { // otherwise it's a bitmap - bitmapAdapter.importBitmap(fileData, fileType).then(value => addCostumeFromBuffer(value)); + bitmapAdapter.importBitmap(fileData, fileType).then(addCostumeFromBuffer); } }; From 397828243581599c0412ecf18e0d0a4d69e523a6 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Thu, 12 Jul 2018 16:48:07 -0400 Subject: [PATCH 5/7] Correct call to addCostumeFromBuffer for svgs --- src/lib/file-uploader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/file-uploader.js b/src/lib/file-uploader.js index a5805c1c8..a0690f2b0 100644 --- a/src/lib/file-uploader.js +++ b/src/lib/file-uploader.js @@ -129,7 +129,7 @@ const costumeUpload = function (fileData, fileType, costumeName, storage, handle // passing in an array buffer causes the sprite/costume // thumbnails to not display because the data URI for the costume // is invalid - addCostumeFromBuffer(null, new Uint8Array(fileData)); + addCostumeFromBuffer(new Uint8Array(fileData)); } else { // otherwise it's a bitmap bitmapAdapter.importBitmap(fileData, fileType).then(addCostumeFromBuffer); From ce070fe0fba8b930affca7d13c54f12d640f3307 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Thu, 12 Jul 2018 17:17:50 -0400 Subject: [PATCH 6/7] Catch errors in load costume --- src/lib/file-uploader.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/file-uploader.js b/src/lib/file-uploader.js index a0690f2b0..53d0ab8f6 100644 --- a/src/lib/file-uploader.js +++ b/src/lib/file-uploader.js @@ -132,7 +132,10 @@ const costumeUpload = function (fileData, fileType, costumeName, storage, handle addCostumeFromBuffer(new Uint8Array(fileData)); } else { // otherwise it's a bitmap - bitmapAdapter.importBitmap(fileData, fileType).then(addCostumeFromBuffer); + bitmapAdapter.importBitmap(fileData, fileType).then(addCostumeFromBuffer) + .catch(e => { + log.error(e); + }); } }; From f59d0283623e8377c6b21eb258e214183f32be69 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Thu, 12 Jul 2018 19:00:56 -0400 Subject: [PATCH 7/7] add dependencies --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 136a6bc41..b95d11479 100644 --- a/package.json +++ b/package.json @@ -101,8 +101,8 @@ "scratch-paint": "0.2.0-prerelease.20180712144339", "scratch-render": "0.1.0-prerelease.20180618173030", "scratch-storage": "0.5.1", - "scratch-svg-renderer": "0.2.0-prerelease.20180618172917", - "scratch-vm": "0.1.0-prerelease.1531340421", + "scratch-svg-renderer": "0.2.0-prerelease.20180712223402", + "scratch-vm": "0.1.0-prerelease.1531436232", "selenium-webdriver": "3.6.0", "startaudiocontext": "1.2.1", "style-loader": "^0.21.0",