mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-08-12 22:42:03 -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.
|
* Activate "event_whenthisspriteclicked" hats.
|
||||||
* @param {number} x X position to be sent to the renderer.
|
* @param {Target} target to trigger hats on.
|
||||||
* @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.
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_activateClickHats (x, y) {
|
_activateClickHats (target) {
|
||||||
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
|
|
||||||
// Activate both "this sprite clicked" and "stage clicked"
|
// Activate both "this sprite clicked" and "stage clicked"
|
||||||
// They were separated into two opcodes for labeling,
|
// They were separated into two opcodes for labeling,
|
||||||
// but should act the same way.
|
// but should act the same way.
|
||||||
|
@ -38,16 +28,28 @@ class Mouse {
|
||||||
null, target);
|
null, target);
|
||||||
this.runtime.startHats('event_whenstageclicked',
|
this.runtime.startHats('event_whenstageclicked',
|
||||||
null, target);
|
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') {
|
if (typeof data.isDown !== 'undefined') {
|
||||||
const previousDownState = this._isDown;
|
const previousDownState = this._isDown;
|
||||||
this._isDown = data.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;
|
const isNewMouseDown = !previousDownState && this._isDown;
|
||||||
// Make sure click is within the canvas bounds to activate click hats
|
const isNewMouseUp = previousDownState && !this._isDown;
|
||||||
if (isNewMouseDown &&
|
|
||||||
data.x > 0 && data.x < data.canvasWidth &&
|
// Draggable targets start click hats on mouse up.
|
||||||
data.y > 0 && data.y < data.canvasHeight) {
|
// Non-draggable targets start click hats on mouse down.
|
||||||
this._activateClickHats(data.x, data.y);
|
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
|
canvasHeight: 360
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dummyTarget = {
|
||||||
|
draggable: false
|
||||||
|
};
|
||||||
|
|
||||||
const mouseDownEvent = Object.assign({}, mouseMoveEvent, {
|
const mouseDownEvent = Object.assign({}, mouseMoveEvent, {
|
||||||
isDown: true
|
isDown: true
|
||||||
});
|
});
|
||||||
|
@ -90,17 +94,19 @@ test('mousedown activating click hats', t => {
|
||||||
isDown: false
|
isDown: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// Stub activateClickHats function for testing
|
// Stub activateClickHats and pick function for testing
|
||||||
let ranClickHats = false;
|
let ranClickHats = false;
|
||||||
m._activateClickHats = () => {
|
m._activateClickHats = () => {
|
||||||
ranClickHats = true;
|
ranClickHats = true;
|
||||||
};
|
};
|
||||||
|
m._pickTarget = () => dummyTarget;
|
||||||
|
|
||||||
// Mouse move without mousedown
|
// Mouse move without mousedown
|
||||||
m.postData(mouseMoveEvent);
|
m.postData(mouseMoveEvent);
|
||||||
t.strictEquals(ranClickHats, false);
|
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);
|
m.postData(mouseDownEvent);
|
||||||
t.strictEquals(ranClickHats, true);
|
t.strictEquals(ranClickHats, true);
|
||||||
|
|
||||||
|
@ -109,10 +115,11 @@ test('mousedown activating click hats', t => {
|
||||||
m.postData(mouseDownEvent);
|
m.postData(mouseDownEvent);
|
||||||
t.strictEquals(ranClickHats, false);
|
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;
|
ranClickHats = false;
|
||||||
|
dummyTarget.draggable = true;
|
||||||
m.postData(mouseUpEvent);
|
m.postData(mouseUpEvent);
|
||||||
t.strictEquals(ranClickHats, false);
|
t.strictEquals(ranClickHats, true);
|
||||||
|
|
||||||
// And hats don't trigger if mouse down is outside canvas
|
// And hats don't trigger if mouse down is outside canvas
|
||||||
ranClickHats = false;
|
ranClickHats = false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue