mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-07-16 17:22:33 -04:00
Add logic to trigger click hats on mouse up on a draggable target
As long as the event was not a drag
This commit is contained in:
parent
9bf7ef8573
commit
e002db48f2
2 changed files with 56 additions and 32 deletions
|
@ -14,21 +14,11 @@ class Mouse {
|
|||
}
|
||||
|
||||
/**
|
||||
* Activate "event_whenthisspriteclicked" hats if needed.
|
||||
* @param {number} x X position to be sent to the renderer.
|
||||
* @param {number} y Y position to be sent to the renderer.
|
||||
* @param {?bool} wasDragged Whether the click event was the result of
|
||||
* a drag end.
|
||||
* Activate "event_whenthisspriteclicked" hats.
|
||||
* @param {Target} target to trigger hats on.
|
||||
* @private
|
||||
*/
|
||||
_activateClickHats (x, y) {
|
||||
if (this.runtime.renderer) {
|
||||
const drawableID = this.runtime.renderer.pick(x, y);
|
||||
for (let i = 0; i < this.runtime.targets.length; i++) {
|
||||
const target = this.runtime.targets[i];
|
||||
if (target.hasOwnProperty('drawableID') &&
|
||||
target.drawableID === drawableID) {
|
||||
// only activate click hat if the mouse up event wasn't
|
||||
_activateClickHats (target) {
|
||||
// Activate both "this sprite clicked" and "stage clicked"
|
||||
// They were separated into two opcodes for labeling,
|
||||
// but should act the same way.
|
||||
|
@ -38,16 +28,28 @@ class Mouse {
|
|||
null, target);
|
||||
this.runtime.startHats('event_whenstageclicked',
|
||||
null, target);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a target by XY location
|
||||
* @param {number} x X position to be sent to the renderer.
|
||||
* @param {number} y Y position to be sent to the renderer.
|
||||
* @return {Target} the target at that location
|
||||
* @private
|
||||
*/
|
||||
_pickTarget (x, y) {
|
||||
if (this.runtime.renderer) {
|
||||
const drawableID = this.runtime.renderer.pick(x, y);
|
||||
for (let i = 0; i < this.runtime.targets.length; i++) {
|
||||
const target = this.runtime.targets[i];
|
||||
if (target.hasOwnProperty('drawableID') &&
|
||||
target.drawableID === drawableID) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
// If haven't returned, activate click hats for stage.
|
||||
// Still using both blocks for sharing compatibility.
|
||||
this.runtime.startHats('event_whenthisspriteclicked',
|
||||
null, this.runtime.getTargetForStage());
|
||||
this.runtime.startHats('event_whenstageclicked',
|
||||
null, this.runtime.getTargetForStage());
|
||||
}
|
||||
// Return the stage if no target was found
|
||||
return this.runtime.getTargetForStage();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,12 +76,27 @@ class Mouse {
|
|||
if (typeof data.isDown !== 'undefined') {
|
||||
const previousDownState = this._isDown;
|
||||
this._isDown = data.isDown;
|
||||
|
||||
// Do not trigger if down state has not changed
|
||||
if (previousDownState === this._isDown) return;
|
||||
|
||||
// Never trigger click hats at the end of a drag
|
||||
if (data.wasDragged) return;
|
||||
|
||||
// Do not activate click hats for clicks outside canvas bounds
|
||||
if (!(data.x > 0 && data.x < data.canvasWidth &&
|
||||
data.y > 0 && data.y < data.canvasHeight)) return;
|
||||
|
||||
const target = this._pickTarget(data.x, data.y);
|
||||
const isNewMouseDown = !previousDownState && this._isDown;
|
||||
// Make sure click is within the canvas bounds to activate click hats
|
||||
if (isNewMouseDown &&
|
||||
data.x > 0 && data.x < data.canvasWidth &&
|
||||
data.y > 0 && data.y < data.canvasHeight) {
|
||||
this._activateClickHats(data.x, data.y);
|
||||
const isNewMouseUp = previousDownState && !this._isDown;
|
||||
|
||||
// Draggable targets start click hats on mouse up.
|
||||
// Non-draggable targets start click hats on mouse down.
|
||||
if (target.draggable && isNewMouseUp) {
|
||||
this._activateClickHats(target);
|
||||
} else if (!target.draggable && isNewMouseDown) {
|
||||
this._activateClickHats(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,10 @@ test('mousedown activating click hats', t => {
|
|||
canvasHeight: 360
|
||||
};
|
||||
|
||||
const dummyTarget = {
|
||||
draggable: false
|
||||
};
|
||||
|
||||
const mouseDownEvent = Object.assign({}, mouseMoveEvent, {
|
||||
isDown: true
|
||||
});
|
||||
|
@ -90,17 +94,19 @@ test('mousedown activating click hats', t => {
|
|||
isDown: false
|
||||
});
|
||||
|
||||
// Stub activateClickHats function for testing
|
||||
// Stub activateClickHats and pick function for testing
|
||||
let ranClickHats = false;
|
||||
m._activateClickHats = () => {
|
||||
ranClickHats = true;
|
||||
};
|
||||
m._pickTarget = () => dummyTarget;
|
||||
|
||||
// Mouse move without mousedown
|
||||
m.postData(mouseMoveEvent);
|
||||
t.strictEquals(ranClickHats, false);
|
||||
|
||||
// Mouse down event triggers the hats
|
||||
// Mouse down event triggers the hats if target is not draggable
|
||||
dummyTarget.draggable = false;
|
||||
m.postData(mouseDownEvent);
|
||||
t.strictEquals(ranClickHats, true);
|
||||
|
||||
|
@ -109,10 +115,11 @@ test('mousedown activating click hats', t => {
|
|||
m.postData(mouseDownEvent);
|
||||
t.strictEquals(ranClickHats, false);
|
||||
|
||||
// And it doesn't trigger on mouse up
|
||||
// And it does trigger on mouse up if target is draggable
|
||||
ranClickHats = false;
|
||||
dummyTarget.draggable = true;
|
||||
m.postData(mouseUpEvent);
|
||||
t.strictEquals(ranClickHats, false);
|
||||
t.strictEquals(ranClickHats, true);
|
||||
|
||||
// And hats don't trigger if mouse down is outside canvas
|
||||
ranClickHats = false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue