Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions extensions/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"files",
"pointerlock",
"cursor",
"legobrainbiker/more mouse controls",
"runtime-options",
"fetch",
"text",
Expand Down
137 changes: 137 additions & 0 deletions extensions/legobrainbiker/more mouse controls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Name: More Mouse Controls
// ID: legobrainbikerMoreMouseControls
// Description: Some features I felt were missing from the mouse, including right click detection.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you make this description a bit more professional and reminiscent of the extension's qualities?

// By: legobrainbiker <https://scratch.mit.edu/users/legobrainbiker/>
// License: MPL-2.0
((Scratch) => {
"use strict";
class moreMouseControls {
constructor() {
this.mouseX = 0;
this.mouseY = 0;
this.scroll = 0;
this.buttons = [];
document.addEventListener("mousewheel", (e) => {
this.mouseWheelDelta = e.deltaY;
Scratch.vm.runtime.startHats(
"legobrainbikerMoreMouseControls_onScroll"
);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On scroll is available in native scratch when doing:

when [up/down arrow] pressed
if <not <up/down arrow pressed>> ?:
    scroll action
endif

Because the hat block detects scrolling but the key boolean doesn't, so you can detect scrolling like this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this, but I thought this would make it easier, especialy when using the other scroll block. also it works with both at the say time.

Copy link
Contributor

@Brackets-Coder Brackets-Coder May 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this, but I thought this would make it easier, especialy when using the other scroll block. also it works with both at the say time.

That's a valid point, but it's still probably not worth adding a whole new extension to the gallery though

document.addEventListener("mouseup", (e) => {
this.buttons[e.button] = false;
});
document.addEventListener("mousedown", (e) => {
this.buttons[e.button] = true;
});
document.addEventListener("mousemove", (e) => {
this.mouseX = e.clientX;
this.mouseY = e.clientY;
});
}
getInfo() {
return {
id: "legobrainbikerMoreMouseControls",
name: Scratch.translate("More Mouse Controls"),
menuIconURI:
"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIzNi4zOTI4MSIgaGVpZ2h0PSIzNS40MjY1OSIgdmlld0JveD0iMCwwLDM2LjM5MjgxLDM1LjQyNjU5Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTU2Ljg4NTQxLC0xNTcuNjM4NDcpIj48ZyBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCI+PHBhdGggZD0iTTE2Mi44NjU0NCwxNjcuNDYzMDljMCwtMi4wNDY3NCAxLjc0NjIsLTMuNzA1OTQgMy45MDAyNCwtMy43MDU5NGMyLjE1NDA0LDAgMy45MDAyNCwxLjY1OTIxIDMuOTAwMjQsMy43MDU5NGMwLDIuMDQ2NzQgLTEuNzQ2MiwzLjcwNTk1IC0zLjkwMDI0LDMuNzA1OTVjLTIuMTU0MDQsMCAtMy45MDAyNCwtMS42NTkyMSAtMy45MDAyNCwtMy43MDU5NXoiIGZpbGw9Im5vbmUiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtbGluZWNhcD0iYnV0dCIvPjxwYXRoIGQ9Ik0xNTguMTM1NDEsMTY3LjQ2MzA5YzAsLTQuNzM1NjMgMy44NjM5LC04LjU3NDYyIDguNjMwMjcsLTguNTc0NjJjNC43NjYzNywwIDguNjMwMjcsMy44Mzg5OSA4LjYzMDI3LDguNTc0NjJjMCw0LjczNTYzIC0zLjg2MzksOC41NzQ2MiAtOC42MzAyNyw4LjU3NDYyYy00Ljc2NjM3LDAgLTguNjMwMjcsLTMuODM4OTkgLTguNjMwMjcsLTguNTc0NjJ6IiBmaWxsPSJub25lIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWxpbmVjYXA9ImJ1dHQiLz48cGF0aCBkPSJNMTY3LjE0OTM5LDE3MC45MDY1YzEuNzMxMTMsMy41NzM5NSA3LjA5NTEzLDE0LjY0ODAxIDkuODg1MzksMjAuNDA4NTVjMS4wNDI2OSwyLjE1MjY1IDIuMzMzMzgsMS4xMzM2NiAyLjc1MjMyLC0wLjU0MjA4YzAuNDY3NjksLTEuODcwNzUgMS41NTMyMywtNi4yMTI5MiAyLjE0OTI5LC04LjU5NzE0YzAuMjQ3MDcsLTAuOTg4MjggMS4yMjc3NCwtMS45Mzk5OCAyLjAwNjEzLC0yLjIyNTM5YzEuMTc1NDYsLTAuNDMxIDQuNjg3NzgsLTEuNzE4ODUgNy41ODU3MSwtMi43ODE0MmMyLjMzMSwtMC44NTQ3IDIuMzU5MTIsLTIuMTQzNTMgLTAuNDQ3MjksLTIuOTk3NjVjLTYuNTM1MzMsLTEuOTg5MDEgLTE3Ljk1NzAzLC01LjQ2NTE4IC0yMS41ODI1MiwtNi41Njg1OWMtMi4xNzUxNCwtMC42NjIgLTMuNDAzNTEsMS4xMjY3MyAtMi4zNDkwMywzLjMwMzczeiIgZmlsbD0iI2EzYTNhMyIgc3Ryb2tlLXdpZHRoPSIzLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPjwvZz48L2c+PC9zdmc+",
blockIconURI:
"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIzNi4zOTI4MSIgaGVpZ2h0PSIzNS40MjY1OSIgdmlld0JveD0iMCwwLDM2LjM5MjgxLDM1LjQyNjU5Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTU2Ljg4NTQxLC0xNTcuNjM4NDcpIj48ZyBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCI+PHBhdGggZD0iTTE2Mi44NjU0NCwxNjcuNDYzMDljMCwtMi4wNDY3NCAxLjc0NjIsLTMuNzA1OTQgMy45MDAyNCwtMy43MDU5NGMyLjE1NDA0LDAgMy45MDAyNCwxLjY1OTIxIDMuOTAwMjQsMy43MDU5NGMwLDIuMDQ2NzQgLTEuNzQ2MiwzLjcwNTk1IC0zLjkwMDI0LDMuNzA1OTVjLTIuMTU0MDQsMCAtMy45MDAyNCwtMS42NTkyMSAtMy45MDAyNCwtMy43MDU5NXoiIGZpbGw9Im5vbmUiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtbGluZWNhcD0iYnV0dCIvPjxwYXRoIGQ9Ik0xNTguMTM1NDEsMTY3LjQ2MzA5YzAsLTQuNzM1NjMgMy44NjM5LC04LjU3NDYyIDguNjMwMjcsLTguNTc0NjJjNC43NjYzNywwIDguNjMwMjcsMy44Mzg5OSA4LjYzMDI3LDguNTc0NjJjMCw0LjczNTYzIC0zLjg2MzksOC41NzQ2MiAtOC42MzAyNyw4LjU3NDYyYy00Ljc2NjM3LDAgLTguNjMwMjcsLTMuODM4OTkgLTguNjMwMjcsLTguNTc0NjJ6IiBmaWxsPSJub25lIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWxpbmVjYXA9ImJ1dHQiLz48cGF0aCBkPSJNMTY3LjE0OTM5LDE3MC45MDY1YzEuNzMxMTMsMy41NzM5NSA3LjA5NTEzLDE0LjY0ODAxIDkuODg1MzksMjAuNDA4NTVjMS4wNDI2OSwyLjE1MjY1IDIuMzMzMzgsMS4xMzM2NiAyLjc1MjMyLC0wLjU0MjA4YzAuNDY3NjksLTEuODcwNzUgMS41NTMyMywtNi4yMTI5MiAyLjE0OTI5LC04LjU5NzE0YzAuMjQ3MDcsLTAuOTg4MjggMS4yMjc3NCwtMS45Mzk5OCAyLjAwNjEzLC0yLjIyNTM5YzEuMTc1NDYsLTAuNDMxIDQuNjg3NzgsLTEuNzE4ODUgNy41ODU3MSwtMi43ODE0MmMyLjMzMSwtMC44NTQ3IDIuMzU5MTIsLTIuMTQzNTMgLTAuNDQ3MjksLTIuOTk3NjVjLTYuNTM1MzMsLTEuOTg5MDEgLTE3Ljk1NzAzLC01LjQ2NTE4IC0yMS41ODI1MiwtNi41Njg1OWMtMi4xNzUxNCwtMC42NjIgLTMuNDAzNTEsMS4xMjY3MyAtMi4zNDkwMywzLjMwMzczeiIgZmlsbD0iI2EzYTNhMyIgc3Ryb2tlLXdpZHRoPSIzLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPjwvZz48L2c+PC9zdmc+",
color1: "#99bbbb",
color2: "#88bbbb",
color3: "#88bbbb",
blocks: [
{
opcode: "onMouseUp",
blockType: Scratch.BlockType.HAT,
text: Scratch.translate("when mouse button [button] is released"),
isEdgeActivated: true,
arguments: {
button: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: "0",
},
},
},
{
opcode: "onMouseDown",
blockType: Scratch.BlockType.HAT,
text: Scratch.translate("when mouse button [button] is pressed"),
isEdgeActivated: true,
arguments: {
button: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: "0",
},
},
},
{
opcode: "buttonPressed",
blockType: Scratch.BlockType.BOOLEAN,
text: Scratch.translate("mouse button [button] is pressed"),
arguments: {
button: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: "0",
},
},
},
{
opcode: "dissableContextMenu",
blockType: Scratch.BlockType.COMMAND,
text: Scratch.translate("disable context menu"),
},
{
opcode: "onScroll",
blockType: Scratch.BlockType.EVENT,
text: Scratch.translate("when scrolling"),
isEdgeActivated: false,
},
{
opcode: "scrollamount",
blockType: Scratch.BlockType.REPORTER,
text: Scratch.translate("scroll amount"),
},
{
opcode: "mouseGlobalX",
blockType: Scratch.BlockType.REPORTER,
text: Scratch.translate("mouse global x position"),
},
{
opcode: "mouseGlobalY",
blockType: Scratch.BlockType.REPORTER,
text: Scratch.translate("mouse global y position"),
},
],
};
}
onMouseUp(args) {
return !this.buttonPressed(args);
}
onMouseDown(args) {
return this.buttonPressed(args);
}
buttonPressed({ button }) {
console.log(button);
console.log(Scratch.Cast.toNumber(button));
console.log(this.buttons[Scratch.Cast.toNumber(button)]);
return this.buttons[Scratch.Cast.toNumber(button)] || false;
}
dissableContextMenu() {
document.addEventListener("contextmenu", (e) => {
e.preventDefault();
});
}
scrollamount() {
return this.mouseWheelDelta || 0;
}
mouseGlobalX() {
const canvas = Scratch.renderer.canvas.getBoundingClientRect();
return this.mouseX - canvas.x - canvas.width / 2;
}
mouseGlobalY() {
const canvas = Scratch.renderer.canvas.getBoundingClientRect();
return -(this.mouseY - canvas.y - canvas.height / 2);
}
}
Scratch.extensions.register(new moreMouseControls());
})(Scratch);
1 change: 1 addition & 0 deletions images/legobrainbiker/more mouse controls.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading