Move the place where we divide rotation center by resolution into the VM. Also revert the method of putting data into storage to the one that was convoluted but working

This commit is contained in:
DD 2018-04-30 16:35:24 -04:00
parent 9f0f2fcd27
commit 78cd327237
2 changed files with 45 additions and 29 deletions

View file

@ -34,6 +34,7 @@
"babel-loader": "^7.0.0", "babel-loader": "^7.0.0",
"babel-preset-es2015": "^6.24.1", "babel-preset-es2015": "^6.24.1",
"buffer-loader": "0.0.1", "buffer-loader": "0.0.1",
"canvas-toBlob": "1.0.0",
"copy-webpack-plugin": "4.2.1", "copy-webpack-plugin": "4.2.1",
"decode-html": "2.0.0", "decode-html": "2.0.0",
"escape-html": "1.0.3", "escape-html": "1.0.3",

View file

@ -2,6 +2,7 @@ const TextEncoder = require('text-encoding').TextEncoder;
const EventEmitter = require('events'); const EventEmitter = require('events');
const JSZip = require('jszip'); const JSZip = require('jszip');
const Buffer = require('buffer').Buffer;
const centralDispatch = require('./dispatch/central-dispatch'); const centralDispatch = require('./dispatch/central-dispatch');
const ExtensionManager = require('./extension-support/extension-manager'); const ExtensionManager = require('./extension-support/extension-manager');
const log = require('./util/log'); const log = require('./util/log');
@ -17,6 +18,7 @@ const Variable = require('./engine/variable');
const {loadCostume} = require('./import/load-costume.js'); const {loadCostume} = require('./import/load-costume.js');
const {loadSound} = require('./import/load-sound.js'); const {loadSound} = require('./import/load-sound.js');
const {serializeSounds, serializeCostumes} = require('./serialization/serialize-assets'); const {serializeSounds, serializeCostumes} = require('./serialization/serialize-assets');
require('canvas-toBlob');
const RESERVED_NAMES = ['_mouse_', '_stage_', '_edge_', '_myself_', '_random_']; const RESERVED_NAMES = ['_mouse_', '_stage_', '_edge_', '_myself_', '_random_'];
@ -554,7 +556,7 @@ class VirtualMachine extends EventEmitter {
return this.runtime.storage.get(id).decodeText(); return this.runtime.storage.get(id).decodeText();
} else if (format === this.runtime.storage.DataFormat.PNG || } else if (format === this.runtime.storage.DataFormat.PNG ||
format === this.runtime.storage.DataFormat.JPG) { format === this.runtime.storage.DataFormat.JPG) {
return this.runtime.storage.get(id).encodeDataURI('image/png'); return this.runtime.storage.get(id).encodeDataURI();
} }
log.error(`Unhandled format: ${this.runtime.storage.get(id).dataFormat}`); log.error(`Unhandled format: ${this.runtime.storage.get(id).dataFormat}`);
return null; return null;
@ -562,41 +564,54 @@ class VirtualMachine extends EventEmitter {
/** /**
* Update a costume with the given bitmap * Update a costume with the given bitmap
* @param {int} costumeIndex - the index of the costume to be updated. * @param {!int} costumeIndex - the index of the costume to be updated.
* @param {ImageData} bitmap - new bitmap for the renderer. * @param {!ImageData} bitmap - new bitmap for the renderer.
* @param {number} rotationCenterX x of point about which the costume rotates, relative to its upper left corner * @param {!number} rotationCenterX x of point about which the costume rotates, relative to its upper left corner
* @param {number} rotationCenterY y of point about which the costume rotates, relative to its upper left corner * @param {!number} rotationCenterY y of point about which the costume rotates, relative to its upper left corner
* @param {number} bitmapResolution 1 for bitmaps that have 1 pixel per unit of stage, * @param {!number} bitmapResolution 1 for bitmaps that have 1 pixel per unit of stage,
* 2 for double-resolution bitmaps * 2 for double-resolution bitmaps
*/ */
updateBitmap (costumeIndex, bitmap, rotationCenterX, rotationCenterY, bitmapResolution) { updateBitmap (costumeIndex, bitmap, rotationCenterX, rotationCenterY, bitmapResolution) {
const costume = this.editingTarget.getCostumes()[costumeIndex]; const costume = this.editingTarget.getCostumes()[costumeIndex];
if (costume && this.runtime && this.runtime.renderer) { if (!(costume && this.runtime && this.runtime.renderer)) return;
costume.rotationCenterX = rotationCenterX;
costume.rotationCenterY = rotationCenterY;
// @todo: updateBitmapSkin does not take ImageData costume.rotationCenterX = rotationCenterX;
const canvas = document.createElement('canvas'); costume.rotationCenterY = rotationCenterY;
canvas.width = bitmap.width;
canvas.height = bitmap.height;
const context = canvas.getContext('2d');
context.putImageData(bitmap, 0, 0);
this.runtime.renderer.updateBitmapSkin( // @todo: updateBitmapSkin does not take ImageData
costume.skinId, canvas, bitmapResolution, [rotationCenterX, rotationCenterY]); const canvas = document.createElement('canvas');
} canvas.width = bitmap.width;
canvas.height = bitmap.height;
const context = canvas.getContext('2d');
context.putImageData(bitmap, 0, 0);
const storage = this.runtime.storage; // Divide by resolution because the renderer's definition of the rotation center
costume.assetId = storage.builtinHelper.cache( // is the rotation center divided by the bitmap resolution
storage.AssetType.ImageBitmap, this.runtime.renderer.updateBitmapSkin(
storage.DataFormat.PNG, costume.skinId,
bitmap.data canvas,
bitmapResolution,
[rotationCenterX / bitmapResolution, rotationCenterY / bitmapResolution]
); );
costume.dataFormat = storage.DataFormat.PNG;
costume.bitmapResolution = bitmapResolution; // @todo there should be a better way to get from ImageData to a decodable storage format
// costume.size = [bitmap.width, bitmap.height]; canvas.toBlob(blob => {
// costume.md5 = `${costume.assetId}.${costume.dataFormat}`; const reader = new FileReader();
this.emitTargetsUpdate(); reader.addEventListener('loadend', () => {
const storage = this.runtime.storage;
costume.assetId = storage.builtinHelper.cache(
storage.AssetType.ImageBitmap,
storage.DataFormat.PNG,
Buffer.from(reader.result)
);
costume.dataFormat = storage.DataFormat.PNG;
costume.bitmapResolution = bitmapResolution;
costume.size = [bitmap.width, bitmap.height];
costume.md5 = `${costume.assetId}.${costume.dataFormat}`;
this.emitTargetsUpdate();
});
reader.readAsArrayBuffer(blob);
});
} }
/** /**