From 11e28111c54d1b92eab8ec46b114f462f52a07b2 Mon Sep 17 00:00:00 2001
From: Ray Schamp <ray@scratch.mit.edu>
Date: Mon, 20 Feb 2017 16:22:13 -0500
Subject: [PATCH 1/2] Activate click hats on mouse up to match 2.0

---
 src/io/mouse.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/io/mouse.js b/src/io/mouse.js
index bcd19087e..4a7361fa4 100644
--- a/src/io/mouse.js
+++ b/src/io/mouse.js
@@ -46,7 +46,7 @@ Mouse.prototype.postData = function (data) {
     }
     if (typeof data.isDown !== 'undefined') {
         this._isDown = data.isDown;
-        if (this._isDown) {
+        if (!this._isDown) {
             this._activateClickHats(data.x, data.y);
         }
     }

From d0cd9cd8972ab93bc5d0241f2cd3bffaed7b8c59 Mon Sep 17 00:00:00 2001
From: Ray Schamp <ray@scratch.mit.edu>
Date: Fri, 3 Mar 2017 09:35:57 -0500
Subject: [PATCH 2/2] Add methods for dragging and dropping sprites

* Add `getTargetIdForDrawableId` to translate between renderer picks and VM targets
* Add `startDrag` to stop sprite motion while dragging
* Add `stopDrag` to return sprite motion after dragging
---
 src/engine/runtime.js          | 12 ++++++++++++
 src/sprites/rendered-target.js | 34 +++++++++++++++++++++++++++------
 src/virtual-machine.js         | 35 ++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 6 deletions(-)

diff --git a/src/engine/runtime.js b/src/engine/runtime.js
index a060d63a7..130c4ae95 100644
--- a/src/engine/runtime.js
+++ b/src/engine/runtime.js
@@ -793,6 +793,18 @@ Runtime.prototype.getSpriteTargetByName = function (spriteName) {
     }
 };
 
+/**
+ * Get a target by its drawable id.
+ * @param {number} drawableID drawable id of target to find
+ * @return {?Target} The target, if found
+ */
+Runtime.prototype.getTargetByDrawableId = function (drawableID) {
+    for (var i = 0; i < this.targets.length; i++) {
+        var target = this.targets[i];
+        if (target.drawableID === drawableID) return target;
+    }
+};
+
 /**
  * Update the clone counter to track how many clones are created.
  * @param {number} changeAmount How many clones have been created/destroyed.
diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js
index d934f72eb..1e60cad48 100644
--- a/src/sprites/rendered-target.js
+++ b/src/sprites/rendered-target.js
@@ -33,6 +33,13 @@ var RenderedTarget = function (sprite, runtime) {
      */
     this.drawableID = null;
 
+    /**
+     * Drag state of this rendered target. If true, x/y position can't be
+     * changed by blocks.
+     * @type {boolean}
+     */
+    this.dragging = false;
+
     /**
      * Map of current graphic effect values.
      * @type {!Object.<string, number>}
@@ -160,11 +167,11 @@ RenderedTarget.prototype.rotationStyle = (
  * Set the X and Y coordinates.
  * @param {!number} x New X coordinate, in Scratch coordinates.
  * @param {!number} y New Y coordinate, in Scratch coordinates.
+ * @param {?boolean} force Force setting X/Y, in case of dragging
  */
-RenderedTarget.prototype.setXY = function (x, y) {
-    if (this.isStage) {
-        return;
-    }
+RenderedTarget.prototype.setXY = function (x, y, force) {
+    if (this.isStage) return;
+    if (this.dragging && !force) return;
     var oldX = this.x;
     var oldY = this.y;
     if (this.renderer) {
@@ -695,11 +702,12 @@ RenderedTarget.prototype.onStopAll = function () {
  * @param {object} data An object with sprite info data to set.
  */
 RenderedTarget.prototype.postSpriteInfo = function (data) {
+    var force = data.hasOwnProperty('force') ? data.force : null;
     if (data.hasOwnProperty('x')) {
-        this.setXY(data.x, this.y);
+        this.setXY(data.x, this.y, force);
     }
     if (data.hasOwnProperty('y')) {
-        this.setXY(this.x, data.y);
+        this.setXY(this.x, data.y, force);
     }
     if (data.hasOwnProperty('direction')) {
         this.setDirection(data.direction);
@@ -712,6 +720,20 @@ RenderedTarget.prototype.postSpriteInfo = function (data) {
     }
 };
 
+/**
+ * Put the sprite into the drag state. While in effect, setXY must be forced
+ */
+RenderedTarget.prototype.startDrag = function () {
+    this.dragging = true;
+};
+
+/**
+ * Remove the sprite from the drag state.
+ */
+RenderedTarget.prototype.stopDrag = function () {
+    this.dragging = false;
+};
+
 /**
  * Serialize sprite info, used when emitting events about the sprite
  * @returns {object} sprite data as a simple object
diff --git a/src/virtual-machine.js b/src/virtual-machine.js
index 1f3bdfa1f..9d8477c45 100644
--- a/src/virtual-machine.js
+++ b/src/virtual-machine.js
@@ -329,6 +329,41 @@ VirtualMachine.prototype.emitWorkspaceUpdate = function () {
     });
 };
 
+/**
+ * Get a target id for a drawable id. Useful for interacting with the renderer
+ * @param {int} drawableId The drawable id to request the target id for
+ * @returns {?string} The target id, if found. Will also be null if the target found is the stage.
+ */
+VirtualMachine.prototype.getTargetIdForDrawableId = function (drawableId) {
+    var target = this.runtime.getTargetByDrawableId(drawableId);
+    if (target.hasOwnProperty('id') && target.hasOwnProperty('isStage') && !target.isStage) {
+        return target.id;
+    }
+    return null;
+};
+
+/**
+ * Put a target into a "drag" state, during which its X/Y positions will be unaffected
+ * by blocks.
+ * @param {string} targetId The id for the target to put into a drag state
+ */
+VirtualMachine.prototype.startDrag = function (targetId) {
+    var target = this.runtime.getTargetById(targetId);
+    if (target) {
+        target.startDrag();
+        this.setEditingTarget(target.id);
+    }
+};
+
+/**
+ * Remove a target from a drag state, so blocks may begin affecting X/Y position again
+ * @param {string} targetId The id for the target to remove from the drag state
+ */
+VirtualMachine.prototype.stopDrag = function (targetId) {
+    var target = this.runtime.getTargetById(targetId);
+    if (target) target.stopDrag();
+};
+
 /**
  * Post/edit sprite info for the current editing target.
  * @param {object} data An object with sprite info data to set.