From 2cffa7b643abf909daa3db10ba5ccf4a326ff91b Mon Sep 17 00:00:00 2001 From: Tim Mickel Date: Wed, 19 Oct 2016 17:02:04 -0400 Subject: [PATCH] Add rotation center and bitmap/costume resolution (#51) --- src/Drawable.js | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Drawable.js b/src/Drawable.js index c91e802..5d07567 100644 --- a/src/Drawable.js +++ b/src/Drawable.js @@ -60,6 +60,7 @@ class Drawable { this._position = twgl.v3.create(0, 0); this._scale = twgl.v3.create(100, 100); + this._rotationCenter = twgl.v3.create(0, 0); this._direction = 90; this._transformDirty = true; this._visible = true; @@ -157,8 +158,9 @@ Drawable.prototype.getID = function () { * The Drawable will continue using the existing skin until the new one loads. * If there is no existing skin, the Drawable will use a 1x1 transparent image. * @param {string} skin_url The URL of the skin. + * @param {number=} opt_costumeResolution Optionally, a resolution for the skin. */ -Drawable.prototype.setSkin = function (skin_url) { +Drawable.prototype.setSkin = function (skin_url, opt_costumeResolution) { // TODO: cache Skins instead of loading each time. Ref count them? // TODO: share Skins across Drawables - see also destroy() if (skin_url) { @@ -171,7 +173,7 @@ Drawable.prototype.setSkin = function (skin_url) { this._setSkinSVG(skin_url); break; default: - this._setSkinBitmap(skin_url); + this._setSkinBitmap(skin_url, opt_costumeResolution); break; } } @@ -213,11 +215,13 @@ Drawable.prototype.getEnabledEffects = function () { /** * Load a bitmap skin. Supports the same formats as the Image element. * @param {string} skin_md5ext The MD5 and file extension of the bitmap skin. + * @param {number=} opt_costumeResolution Optionally, a resolution for the skin. * @private */ -Drawable.prototype._setSkinBitmap = function (skin_md5ext) { +Drawable.prototype._setSkinBitmap = function (skin_md5ext, + opt_costumeResolution) { var url = skin_md5ext; - this._setSkinCore(url, 2); + this._setSkinCore(url, opt_costumeResolution); }; /** @@ -311,7 +315,7 @@ Drawable.prototype.getVisible = function () { Drawable.prototype.updateProperties = function (properties) { var dirty = false; if ('skin' in properties) { - this.setSkin(properties.skin); + this.setSkin(properties.skin, properties.costumeResolution); this.setConvexHullDirty(); } if ('position' in properties && ( @@ -332,6 +336,13 @@ Drawable.prototype.updateProperties = function (properties) { this._scale[1] = properties.scale[1]; dirty = true; } + if ('rotationCenter' in properties && ( + this._rotationCenter[0] != properties.rotationCenter[0] || + this._rotationCenter[1] != properties.rotationCenter[1])) { + this._rotationCenter[0] = properties.rotationCenter[0]; + this._rotationCenter[1] = properties.rotationCenter[1]; + dirty = true; + } if ('visible' in properties) { this._visible = properties.visible; this.setConvexHullDirty(); @@ -401,6 +412,17 @@ Drawable.prototype._calculateTransform = function () { var rotation = (270 - this._direction) * Math.PI / 180; twgl.m4.rotateZ(modelMatrix, rotation, modelMatrix); + + // Adjust rotation center relative to the skin. + var rotationAdjusted = twgl.v3.subtract( + this._rotationCenter, + twgl.v3.divScalar(this._uniforms.u_skinSize, 2) + ); + rotationAdjusted[1] *= -1; // Y flipped to Scratch coordinate. + rotationAdjusted[2] = 0; // Z coordinate is 0. + + twgl.m4.translate(modelMatrix, rotationAdjusted, modelMatrix); + var scaledSize = twgl.v3.divScalar(twgl.v3.multiply( this._uniforms.u_skinSize, this._scale), 100); scaledSize[2] = 0; // was NaN because the vectors have only 2 components.