diff --git a/src/lib/extensions.js b/src/lib/extensions.js index e3b79b35..51095ed8 100644 --- a/src/lib/extensions.js +++ b/src/lib/extensions.js @@ -571,5 +571,14 @@ export default [ banner: "Gen1x/mw-placeholder.avif", creator: "G1nX", }, + { + name: "Cursor Controls", + description: "Lock and hide your pointer while recording your mouse movement best to use in 3d games.", + code: "codemaster/cursor-controls.js", + banner: "codemaster/cursor-controls.png", + creator: "moosanaeempc-lgtm", + creatorAlias: "codemaster", + isGitHub: true, + }, */ ]; diff --git a/static/extensions/codemaster/cursor-controls.js b/static/extensions/codemaster/cursor-controls.js new file mode 100644 index 00000000..f5d6b996 --- /dev/null +++ b/static/extensions/codemaster/cursor-controls.js @@ -0,0 +1,89 @@ +// Please run this extension without sandbox + +(function(Scratch) { + 'use strict'; + + let moveX = 0; + let moveY = 0; + let lastRealX = null; + let lastRealY = null; + + class CursorControls { + getInfo() { + return { + id: 'moosanaeempclgtmcursorcontrols', + name: 'Cursor Controls', + color1: '#4fc694', + blocks: [ + { + opcode: 'lockPointer', + blockType: Scratch.BlockType.COMMAND, + text: 'lock pointer' + }, + { + opcode: 'unlockPointer', + blockType: Scratch.BlockType.COMMAND, + text: 'unlock pointer' + }, + { + opcode: 'isPointerLocked', + blockType: Scratch.BlockType.BOOLEAN, + text: 'pointer locked?' + }, + { + opcode: 'getMovementX', + blockType: Scratch.BlockType.REPORTER, + text: 'mouse movement x' + }, + { + opcode: 'getMovementY', + blockType: Scratch.BlockType.REPORTER, + text: 'mouse movement y' + } + ] + }; + } + + lockPointer() { + const canvas = document.querySelector('canvas'); + if (canvas) canvas.requestPointerLock(); + } + + unlockPointer() { + if (document.exitPointerLock) { + document.exitPointerLock(); + } + } + + isPointerLocked() { + return !!document.pointerLockElement; + } + + getMovementX() { return moveX; } + getMovementY() { return moveY; } + } + + document.addEventListener('mousemove', (e) => { + if (document.pointerLockElement) { + moveX += e.movementX; + moveY += -e.movementY; + } else { + if (lastRealX !== null && lastRealY !== null) { + moveX += e.clientX - lastRealX; + moveY += -(e.clientY - lastRealY); + } + } + lastRealX = e.clientX; + lastRealY = e.clientY; + }); + + const runtime = Scratch.vm ? Scratch.vm.runtime : Scratch.runtime; + if (runtime) { + runtime.on('RUNTIME_STEP_END', () => { + moveX = 0; + moveY = 0; + }); + } + + Scratch.extensions.register(new CursorControls()); +})(Scratch); diff --git a/static/images/codemaster/cursor-controls.png b/static/images/codemaster/cursor-controls.png new file mode 100644 index 00000000..dfa6391c Binary files /dev/null and b/static/images/codemaster/cursor-controls.png differ