From 079c8a0fadc49045a2afd2079874827602dd832d Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:41:07 +0100 Subject: [PATCH 01/46] Create tsete.txt --- extensions/Eaielectronic/tsete.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 extensions/Eaielectronic/tsete.txt diff --git a/extensions/Eaielectronic/tsete.txt b/extensions/Eaielectronic/tsete.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/extensions/Eaielectronic/tsete.txt @@ -0,0 +1 @@ + From 81926903d8a4f01343880d883f64516941d77a38 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:42:10 +0100 Subject: [PATCH 02/46] Add files via upload --- extensions/Eaielectronic/Finger mutli-mobile | 159 ++++++++++ extensions/Eaielectronic/Fps-returne | 73 +++++ extensions/Eaielectronic/Login page | 256 ++++++++++++++++ .../Eaielectronic/ScrollingTextBubble.js | 275 ++++++++++++++++++ 4 files changed, 763 insertions(+) create mode 100644 extensions/Eaielectronic/Finger mutli-mobile create mode 100644 extensions/Eaielectronic/Fps-returne create mode 100644 extensions/Eaielectronic/Login page create mode 100644 extensions/Eaielectronic/ScrollingTextBubble.js diff --git a/extensions/Eaielectronic/Finger mutli-mobile b/extensions/Eaielectronic/Finger mutli-mobile new file mode 100644 index 0000000000..ef80d822d3 --- /dev/null +++ b/extensions/Eaielectronic/Finger mutli-mobile @@ -0,0 +1,159 @@ +// Name: Finger ios/android +// ID: multiTouchDetection +// Description: Detect multiple fingers on mobile devices. Unlike sensing+ works on all mobile devices. +// By: serpent1867 { + const canvas = Scratch.renderer.canvas; // Récupère le canvas de Scratch + const rect = canvas.getBoundingClientRect(); // Récupère la position du canvas + const scratchX = ((touch.clientX - rect.left) / rect.width) * 480 - 240; + const scratchY = 180 - ((touch.clientY - rect.top) / rect.height) * 360; + return { x: scratchX, y: scratchY }; + }; + + const touchHandler = (event) => { + // Met à jour les coordonnées des doigts dans le tableau + for (let i = 0; i < event.touches.length && i < 10; i++) { + const touch = event.touches[i]; + const { x, y } = convertToScratchCoords(touch); + this.touches[i] = { x, y }; + } + + // Réinitialise les positions restantes si moins de doigts + for (let i = event.touches.length; i < 10; i++) { + this.touches[i] = { x: 0, y: 0 }; + } + }; + + window.addEventListener('touchstart', touchHandler); + window.addEventListener('touchmove', touchHandler); + window.addEventListener('touchend', touchHandler); + } + + // Obtenir la position X du toucher d'un doigt donné + getTouchX(args) { + const index = Math.max(0, Math.min(9, args.INDEX - 1)); // Limite à 10 doigts + return this.touches[index].x; + } + + // Obtenir la position Y du toucher d'un doigt donné + getTouchY(args) { + const index = Math.max(0, Math.min(9, args.INDEX - 1)); // Limite à 10 doigts + return this.touches[index].y; + } + + // Nouveau: Obtenir la position X d'un doigt touchant un sprite + getTouchXOnSprite(args, util) { + const spriteBounds = util.target.getBounds(); + + // Cherche le premier doigt touchant le sprite et renvoie sa position X + for (let i = 0; i < this.touches.length; i++) { + const touch = this.touches[i]; + if (spriteBounds.left <= touch.x && touch.x <= spriteBounds.right && + spriteBounds.bottom <= touch.y && touch.y <= spriteBounds.top) { + return touch.x; + } + } + return 0; // Retourne 0 si aucun doigt ne touche le sprite + } + + // Nouveau: Obtenir la position Y d'un doigt touchant un sprite + getTouchYOnSprite(args, util) { + const spriteBounds = util.target.getBounds(); + + // Cherche le premier doigt touchant le sprite et renvoie sa position Y + for (let i = 0; i < this.touches.length; i++) { + const touch = this.touches[i]; + if (spriteBounds.left <= touch.x && touch.x <= spriteBounds.right && + spriteBounds.bottom <= touch.y && touch.y <= spriteBounds.top) { + return touch.y; + } + } + return 0; // Retourne 0 si aucun doigt ne touche le sprite + } + } + + Scratch.extensions.register(new MultiTouchDetection()); +})(Scratch); diff --git a/extensions/Eaielectronic/Fps-returne b/extensions/Eaielectronic/Fps-returne new file mode 100644 index 0000000000..26898a056c --- /dev/null +++ b/extensions/Eaielectronic/Fps-returne @@ -0,0 +1,73 @@ +// Name: FPS returne +// ID: fpsbasedreturn +// Description: allows you to create games that run at the same speed, even if the FPS changes. +// By: serpent1867 +// License: MPL-2.0 +class FPSBasedReturn { + constructor() { + this.previousTime = null; // Pour stocker l'heure de la dernière frame + this.fpsValue = 30; // Initialiser avec une valeur par défaut (30 FPS) + } + + getInfo() { + return { + id: 'fpsbasedreturn', + name: 'FPS Based Return', + blocks: [ + { + opcode: 'getFPSMultiplier', + blockType: Scratch.BlockType.REPORTER, + text: 'FPS multiplier (based on [REFERENCE] FPS', + arguments: { + REFERENCE: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 30 + } + } + }, + { + opcode: 'getCurrentFPS', + blockType: Scratch.BlockType.REPORTER, + text: 'current FPS' + } + ] + }; + } + + // Méthode pour obtenir le delta time et calculer une fois les FPS + calculateFPS() { + const currentTime = performance.now(); + + if (this.previousTime === null) { + this.previousTime = currentTime; + return; // Attendre jusqu'à la prochaine frame pour calculer le delta time + } + + let deltaTime = (currentTime - this.previousTime) / 1000; // Convertir en secondes + this.previousTime = currentTime; + + if (deltaTime > 1/30) { + deltaTime = 1/30; // Limiter à 30 FPS max pour éviter des pics + } + + this.fpsValue = 1 / deltaTime; // Calculer les FPS actuels + } + + // Méthode pour retourner le FPS actuel + getCurrentFPS() { + this.calculateFPS(); // Mettre à jour le FPS + return this.fpsValue; // Retourner la valeur des FPS actuels + } + + // Méthode pour calculer le multiplicateur en fonction des FPS + getFPSMultiplier(args) { + const referenceFPS = args.REFERENCE; // FPS de référence choisi par l'utilisateur + const fps = this.getCurrentFPS(); // Obtenir les FPS actuels + + const multiplier = referenceFPS / fps; // Le rapport par rapport au FPS de référence + return multiplier; + } +} + +// Enregistrer l'extension dans TurboWarp +Scratch.extensions.register(new FPSBasedReturn()); diff --git a/extensions/Eaielectronic/Login page b/extensions/Eaielectronic/Login page new file mode 100644 index 0000000000..68b71728f0 --- /dev/null +++ b/extensions/Eaielectronic/Login page @@ -0,0 +1,256 @@ +// Name: Login +// ID: usermanagement +// Description: Allows you to create login forms. +// By: Serpent1867 +// License: MPL-2.0 +class UserManagement { + constructor() { + this.users = []; + this.username = ''; + this.password = ''; + this.email = ''; + this.turbowarp = ''; // Variable for the form state + } + + getInfo() { + return { + id: 'usermanagement', + name: 'User Management', + color1: '#ff3f00', // Slightly darker blue + blocks: [ + { + opcode: 'openForm', + blockType: Scratch.BlockType.COMMAND, + text: 'open form for [ACTION]', + arguments: { + ACTION: { + type: Scratch.ArgumentType.STRING, + menu: 'actionsMenu', + defaultValue: 'login' + } + } + }, + { + opcode: 'hideForm', + blockType: Scratch.BlockType.COMMAND, + text: 'hide form', + }, + { + opcode: 'getUsername', + blockType: Scratch.BlockType.REPORTER, + text: 'username', + }, + { + opcode: 'getPassword', + blockType: Scratch.BlockType.REPORTER, + text: 'password', + }, + { + opcode: 'getEmail', + blockType: Scratch.BlockType.REPORTER, + text: 'email', + }, + { + opcode: 'getFormState', + blockType: Scratch.BlockType.REPORTER, + text: 'form state', + }, + { + opcode: 'clear', + blockType: Scratch.BlockType.COMMAND, + text: 'clear values', + } + ], + menus: { + actionsMenu: { + items: ['login', 'create account', 'recover password'] + } + } + }; + } + + openForm(args) { + const { ACTION } = args; + this.turbowarp = ACTION; // Update the form state + this.hideForm(false); // Hide the previous form if open + + const form = document.createElement('form'); + form.style.position = 'absolute'; + form.style.top = '50%'; + form.style.left = '50%'; + form.style.transform = 'translate(-50%, -50%)'; + form.style.padding = '20px'; + form.style.backgroundColor = '#f9f9f9'; + form.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)'; + form.style.borderRadius = '8px'; + form.style.width = '300px'; + form.style.fontFamily = 'Arial, sans-serif'; + + const closeButton = document.createElement('span'); + closeButton.textContent = '✖'; + closeButton.style.position = 'absolute'; + closeButton.style.top = '10px'; + closeButton.style.right = '10px'; + closeButton.style.cursor = 'pointer'; + closeButton.style.color = '#000'; + closeButton.addEventListener('click', () => { + this.hideForm(); + }); + form.appendChild(closeButton); + + const title = document.createElement('h2'); + title.textContent = ACTION.charAt(0).toUpperCase() + ACTION.slice(1); + title.style.textAlign = 'center'; + title.style.color = '#333'; + form.appendChild(title); + + if (ACTION === 'login' || ACTION === 'create account') { + const usernameInput = document.createElement('input'); + usernameInput.type = 'text'; + usernameInput.name = 'username'; + usernameInput.placeholder = 'Username'; + usernameInput.style.width = '90%'; + usernameInput.style.padding = '10px'; + usernameInput.style.margin = '10px 0'; + usernameInput.style.border = '1px solid #ccc'; + usernameInput.style.borderRadius = '4px'; + form.appendChild(usernameInput); + + const passwordInput = document.createElement('input'); + passwordInput.type = 'password'; + passwordInput.name = 'password'; + passwordInput.placeholder = 'Password'; + passwordInput.style.width = '90%'; + passwordInput.style.padding = '10px'; + passwordInput.style.margin = '10px 0'; + passwordInput.style.border = '1px solid #ccc'; + passwordInput.style.borderRadius = '4px'; + form.appendChild(passwordInput); + } + + if (ACTION === 'create account' || ACTION === 'recover password') { + const emailInput = document.createElement('input'); + emailInput.type = 'email'; + emailInput.name = 'email'; + emailInput.placeholder = 'Email'; + emailInput.style.width = '95%'; + emailInput.style.padding = '10px'; + emailInput.style.margin = '10px 0'; + emailInput.style.border = '1px solid #ccc'; + emailInput.style.borderRadius = '4px'; + form.appendChild(emailInput); + } + + const submitButton = document.createElement('button'); + submitButton.type = 'submit'; + submitButton.textContent = 'Send'; + submitButton.style.width = '100%'; + submitButton.style.padding = '10px'; + submitButton.style.margin = '10px 0'; + submitButton.style.backgroundColor = '#4CAF50'; + submitButton.style.color = '#fff'; + submitButton.style.border = 'none'; + submitButton.style.borderRadius = '4px'; + submitButton.style.cursor = 'pointer'; + form.appendChild(submitButton); + + const resetPasswordLink = document.createElement('a'); + resetPasswordLink.textContent = 'Reset password'; + resetPasswordLink.style.display = 'block'; + resetPasswordLink.style.textAlign = 'center'; + resetPasswordLink.style.marginTop = '10px'; + resetPasswordLink.style.color = '#007BFF'; + resetPasswordLink.style.cursor = 'pointer'; + resetPasswordLink.addEventListener('click', () => { + this.hideForm(false); + this.openForm({ ACTION: 'recover password' }); + }); + form.appendChild(resetPasswordLink); + + const createAccountLink = document.createElement('a'); + createAccountLink.textContent = 'Account creation'; + createAccountLink.style.display = 'block'; + createAccountLink.style.textAlign = 'center'; + createAccountLink.style.marginTop = '10px'; + createAccountLink.style.color = '#007BFF'; + createAccountLink.style.cursor = 'pointer'; + createAccountLink.addEventListener('click', () => { + this.hideForm(false); + this.openForm({ ACTION: 'create account' }); + }); + form.appendChild(createAccountLink); + + document.body.appendChild(form); + + form.addEventListener('submit', (event) => { + event.preventDefault(); + const formData = new FormData(form); + this.username = formData.get('username'); + this.password = formData.get('password'); + this.email = formData.get('email'); + + if (ACTION === 'login') { + this.login({ USERNAME: this.username, PASSWORD: this.password }); + } else if (ACTION === 'create account') { + this.createAccount({ USERNAME: this.username, PASSWORD: this.password, EMAIL: this.email }); + } else if (ACTION === 'recover password') { + this.recoverPassword({ EMAIL: this.email }); + } + + this.hideForm(false); + }); + } + + hideForm() { + const form = document.querySelector('form'); + if (form) { + document.body.removeChild(form); + this.turbowarp = ''; // Reset the form state + } + } + + createAccount(args) { + const { USERNAME, PASSWORD, EMAIL } = args; + const user = { username: USERNAME, password: PASSWORD, email: EMAIL }; + this.users.push(user); + console.log(`Account created for ${USERNAME}`); + } + + login(args) { + const { USERNAME, PASSWORD } = args; + const user = this.users.find(u => u.username === USERNAME && u.password === PASSWORD); + console.log(user ? `Login successful for ${USERNAME}` : 'Incorrect username or password.'); + } + + recoverPassword(args) { + const { EMAIL } = args; + const user = this.users.find(u => u.email === EMAIL); + console.log(user ? `Your password is: ${user.password}` : 'Email not found.'); + } + + getUsername() { + return this.username; + } + + getPassword() { + return this.password; + } + + getEmail() { + return this.email; + } + + getFormState() { + return this.turbowarp; + } + + clear() { + this.username = ''; + this.password = ''; + this.email = ''; + console.log('Values have been cleared.'); + } + } + + Scratch.extensions.register(new UserManagement()); + diff --git a/extensions/Eaielectronic/ScrollingTextBubble.js b/extensions/Eaielectronic/ScrollingTextBubble.js new file mode 100644 index 0000000000..e8579fdc37 --- /dev/null +++ b/extensions/Eaielectronic/ScrollingTextBubble.js @@ -0,0 +1,275 @@ +// Name: Scrolling bull +// ID: scrollingTextBubble', +// Description: Create scrolling text bubbles and apply styles with Html tags. +// By: serpent1867 +// License: MPL-2.0 +(function(Scratch) { + 'use strict'; + + class ScrollingTextBubble { + constructor() { + this.bubbles = {}; + this.defaultBubbleStyle = { + backgroundColor: 'rgba(255, 255, 255, 0.8)', + borderColor: 'black', + borderWidth: '2px', + borderRadius: '10px', + boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', + padding: '15px' // Valeur par défaut du padding + }; + } + + getInfo() { + return { + id: 'scrollingTextBubble', + name: 'Scrolling Text Bubble', + blocks: [ + { + opcode: 'showTextBubble', + blockType: Scratch.BlockType.COMMAND, + text: 'show text bubble with text [TEXT] next to sprite with speed [SPEED], font [FONT], width [WIDTH], offsetX [OFFSETX], offsetY [OFFSETY]', + arguments: { + TEXT: { + type: Scratch.ArgumentType.STRING, + defaultValue: 'Hello, World!' + }, + SPEED: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 50 + }, + FONT: { + type: Scratch.ArgumentType.STRING, + defaultValue: 'Arial' + }, + WIDTH: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 200 + }, + OFFSETX: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 0 + }, + OFFSETY: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: -60 + } + }, + filter: [Scratch.TargetType.SPRITE] + }, + { + opcode: 'hideTextBubble', + blockType: Scratch.BlockType.COMMAND, + text: 'hide text bubble', + filter: [Scratch.TargetType.SPRITE] + }, + { + opcode: 'hideAllTextBubbles', + blockType: Scratch.BlockType.COMMAND, + text: 'hide all text bubbles' + }, + { + opcode: 'setBubbleColor', + blockType: Scratch.BlockType.COMMAND, + text: 'set bubble color to [COLOR]', + arguments: { + COLOR: { + type: Scratch.ArgumentType.COLOR, + defaultValue: '#ffffff' + } + } + }, + { + opcode: 'setBubbleStyle', + blockType: Scratch.BlockType.COMMAND, + text: 'set bubble style to [STYLE]', + arguments: { + STYLE: { + type: Scratch.ArgumentType.STRING, + menu: 'bubbleStyleMenu', + defaultValue: 'default' + } + } + }, + { + opcode: 'setBubblePadding', + blockType: Scratch.BlockType.COMMAND, + text: 'set bubble padding to [PADDING]', + arguments: { + PADDING: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 15 // Valeur par défaut pour le padding + } + } + } + ], + menus: { + bubbleStyleMenu: { + acceptReporters: true, + items: ['default', 'rounded', 'sharp', 'shadow', 'no-border'] + } + } + }; + } + + showTextBubble(args, util) { + const sprite = util.target; + const text = args.TEXT; + const speed = args.SPEED; + const font = args.FONT; + const width = args.WIDTH; + const offsetX = args.OFFSETX; + const offsetY = args.OFFSETY; + + if (this.bubbles[sprite.id]) { + clearInterval(this.bubbles[sprite.id].intervalId); + this.bubbles[sprite.id].bubbleDiv.remove(); + } + + const bubbleDiv = document.createElement('div'); + bubbleDiv.style.position = 'absolute'; + this.applyBubbleStyle(bubbleDiv); + bubbleDiv.style.maxWidth = `${width}px`; + bubbleDiv.style.overflow = 'hidden'; + bubbleDiv.style.whiteSpace = 'pre-wrap'; + bubbleDiv.style.fontFamily = font; + bubbleDiv.style.color = 'black'; + bubbleDiv.style.fontSize = '16px'; + bubbleDiv.style.lineHeight = '1.5'; + + const canvas = Scratch.renderer.canvas; + const rect = canvas.getBoundingClientRect(); + + const textContainer = document.createElement('span'); + bubbleDiv.appendChild(textContainer); + document.body.appendChild(bubbleDiv); + + const updateBubblePosition = () => { + const { x, y } = sprite; + + const proportionX = rect.width / 480; + const proportionY = rect.height / 360; + + const adjustedOffsetX = offsetX * proportionX; + const adjustedOffsetY = offsetY * proportionY; + + bubbleDiv.style.left = `${rect.left + (x + 240) / 480 * rect.width + adjustedOffsetX}px`; + bubbleDiv.style.top = `${rect.top + (180 - y) / 360 * rect.height + adjustedOffsetY}px`; + }; + + updateBubblePosition(); + window.addEventListener('mousemove', updateBubblePosition); + + const formattedText = this.formatText(text); + const textParts = this.splitText(formattedText); + + let index = 0; + let currentHTML = ''; + + const intervalId = setInterval(() => { + if (index < textParts.length) { + currentHTML += textParts[index]; + textContainer.innerHTML = currentHTML; + index++; + } else { + clearInterval(intervalId); + } + }, speed); + + this.bubbles[sprite.id] = { intervalId, bubbleDiv }; + } + + hideTextBubble(args, util) { + const sprite = util.target; + + if (this.bubbles[sprite.id]) { + clearInterval(this.bubbles[sprite.id].intervalId); + this.bubbles[sprite.id].bubbleDiv.remove(); + delete this.bubbles[sprite.id]; + } + } + + hideAllTextBubbles() { + for (const spriteId in this.bubbles) { + if (this.bubbles.hasOwnProperty(spriteId)) { + clearInterval(this.bubbles[spriteId].intervalId); + this.bubbles[spriteId].bubbleDiv.remove(); + delete this.bubbles[spriteId]; + } + } + } + + setBubbleColor(args) { + const color = args.COLOR; + this.defaultBubbleStyle.backgroundColor = color; + } + + setBubblePadding(args) { + const padding = args.PADDING; + this.defaultBubbleStyle.padding = `${padding}px`; + } + + setBubbleStyle(args) { + const style = args.STYLE; + + switch (style) { + case 'rounded': + this.defaultBubbleStyle.borderRadius = '20px'; + break; + case 'sharp': + this.defaultBubbleStyle.borderRadius = '0px'; + break; + case 'shadow': + this.defaultBubbleStyle.boxShadow = '0 8px 16px rgba(0, 0, 0, 0.5)'; + break; + case 'no-border': + this.defaultBubbleStyle.borderWidth = '0px'; + break; + default: + this.defaultBubbleStyle = { + backgroundColor: 'rgba(255, 255, 255, 0.8)', + borderColor: 'black', + borderWidth: '2px', + borderRadius: '10px', + boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', + padding: '15px' + }; + break; + } + } + + applyBubbleStyle(bubbleDiv) { + bubbleDiv.style.backgroundColor = this.defaultBubbleStyle.backgroundColor; + bubbleDiv.style.border = `${this.defaultBubbleStyle.borderWidth} solid ${this.defaultBubbleStyle.borderColor}`; + bubbleDiv.style.borderRadius = this.defaultBubbleStyle.borderRadius; + bubbleDiv.style.boxShadow = this.defaultBubbleStyle.boxShadow; + bubbleDiv.style.padding = this.defaultBubbleStyle.padding; + } + + formatText(text) { + // Retourne le texte brut, seules les balises HTML sont interprétées + return text; + } + + splitText(text) { + const parts = []; + const tagRegex = /<\/?[^>]+>/g; + let lastIndex = 0; + + text.replace(tagRegex, (match, index) => { + if (index > lastIndex) { + parts.push(...text.slice(lastIndex, index).split('')); + } + parts.push(match); + lastIndex = index + match.length; + }); + + if (lastIndex < text.length) { + parts.push(...text.slice(lastIndex).split('')); + } + + return parts; + } + } + + Scratch.extensions.register(new ScrollingTextBubble()); +})(Scratch); From e08a5ded3d177799e03da1510ea7cd21308768c8 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:42:28 +0100 Subject: [PATCH 03/46] Delete extensions/Eaielectronic/tsete.txt --- extensions/Eaielectronic/tsete.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 extensions/Eaielectronic/tsete.txt diff --git a/extensions/Eaielectronic/tsete.txt b/extensions/Eaielectronic/tsete.txt deleted file mode 100644 index 8b13789179..0000000000 --- a/extensions/Eaielectronic/tsete.txt +++ /dev/null @@ -1 +0,0 @@ - From 62452cd2cf81ea14bca7a6761b52bb5cb07c1b1f Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:42:58 +0100 Subject: [PATCH 04/46] Rename Finger mutli-mobile to Finger-mutli-mobile.js --- .../Eaielectronic/{Finger mutli-mobile => Finger-mutli-mobile.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename extensions/Eaielectronic/{Finger mutli-mobile => Finger-mutli-mobile.js} (100%) diff --git a/extensions/Eaielectronic/Finger mutli-mobile b/extensions/Eaielectronic/Finger-mutli-mobile.js similarity index 100% rename from extensions/Eaielectronic/Finger mutli-mobile rename to extensions/Eaielectronic/Finger-mutli-mobile.js From c418acf3a387fc588a975697eb7bb1ee824fe5a2 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:43:14 +0100 Subject: [PATCH 05/46] Rename Fps-returne to Fps-returne.js --- extensions/Eaielectronic/{Fps-returne => Fps-returne.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename extensions/Eaielectronic/{Fps-returne => Fps-returne.js} (100%) diff --git a/extensions/Eaielectronic/Fps-returne b/extensions/Eaielectronic/Fps-returne.js similarity index 100% rename from extensions/Eaielectronic/Fps-returne rename to extensions/Eaielectronic/Fps-returne.js From ef61a2e7f5295fbb9227dab9db6299623985b38b Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:43:30 +0100 Subject: [PATCH 06/46] Rename Login page to Login-page.js --- extensions/Eaielectronic/{Login page => Login-page.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename extensions/Eaielectronic/{Login page => Login-page.js} (100%) diff --git a/extensions/Eaielectronic/Login page b/extensions/Eaielectronic/Login-page.js similarity index 100% rename from extensions/Eaielectronic/Login page rename to extensions/Eaielectronic/Login-page.js From 48d84fb7c74673e31d35a649a4a2d54d6d5eb075 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:43:43 +0100 Subject: [PATCH 07/46] Update Login-page.js From 42ad742eb0664277f8fee3cfdad7b8d9c0137590 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:44:15 +0100 Subject: [PATCH 08/46] Update ScrollingTextBubble.js --- extensions/Eaielectronic/ScrollingTextBubble.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/Eaielectronic/ScrollingTextBubble.js b/extensions/Eaielectronic/ScrollingTextBubble.js index e8579fdc37..a3b7d10ed2 100644 --- a/extensions/Eaielectronic/ScrollingTextBubble.js +++ b/extensions/Eaielectronic/ScrollingTextBubble.js @@ -1,7 +1,7 @@ // Name: Scrolling bull // ID: scrollingTextBubble', // Description: Create scrolling text bubbles and apply styles with Html tags. -// By: serpent1867 +// By: SERPENT1867 // License: MPL-2.0 (function(Scratch) { 'use strict'; From a73cd317016a62568101cba9fc94f6d2bdb58715 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:44:29 +0100 Subject: [PATCH 09/46] Update Login-page.js --- extensions/Eaielectronic/Login-page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/Eaielectronic/Login-page.js b/extensions/Eaielectronic/Login-page.js index 68b71728f0..7c01711070 100644 --- a/extensions/Eaielectronic/Login-page.js +++ b/extensions/Eaielectronic/Login-page.js @@ -1,7 +1,7 @@ // Name: Login // ID: usermanagement // Description: Allows you to create login forms. -// By: Serpent1867 +// By: SERPENT1867 // License: MPL-2.0 class UserManagement { constructor() { From c854e96bc0411a894a664bce2d083a7d7699faf5 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:44:43 +0100 Subject: [PATCH 10/46] Update Fps-returne.js --- extensions/Eaielectronic/Fps-returne.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/Eaielectronic/Fps-returne.js b/extensions/Eaielectronic/Fps-returne.js index 26898a056c..958a145341 100644 --- a/extensions/Eaielectronic/Fps-returne.js +++ b/extensions/Eaielectronic/Fps-returne.js @@ -1,7 +1,7 @@ // Name: FPS returne // ID: fpsbasedreturn // Description: allows you to create games that run at the same speed, even if the FPS changes. -// By: serpent1867 +// By: SERPENT1867 // License: MPL-2.0 class FPSBasedReturn { constructor() { From a5e821f6699f28084411af530c146c8bef66a848 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:44:58 +0100 Subject: [PATCH 11/46] Update Finger-mutli-mobile.js --- extensions/Eaielectronic/Finger-mutli-mobile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/Eaielectronic/Finger-mutli-mobile.js b/extensions/Eaielectronic/Finger-mutli-mobile.js index ef80d822d3..70bf41a306 100644 --- a/extensions/Eaielectronic/Finger-mutli-mobile.js +++ b/extensions/Eaielectronic/Finger-mutli-mobile.js @@ -1,7 +1,7 @@ // Name: Finger ios/android // ID: multiTouchDetection // Description: Detect multiple fingers on mobile devices. Unlike sensing+ works on all mobile devices. -// By: serpent1867 Date: Tue, 5 Nov 2024 18:46:22 +0100 Subject: [PATCH 12/46] Update Finger-mutli-mobile.js --- extensions/Eaielectronic/Finger-mutli-mobile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/Eaielectronic/Finger-mutli-mobile.js b/extensions/Eaielectronic/Finger-mutli-mobile.js index 70bf41a306..8a49a26478 100644 --- a/extensions/Eaielectronic/Finger-mutli-mobile.js +++ b/extensions/Eaielectronic/Finger-mutli-mobile.js @@ -1,6 +1,7 @@ // Name: Finger ios/android // ID: multiTouchDetection // Description: Detect multiple fingers on mobile devices. Unlike sensing+ works on all mobile devices. +// By: Eaielectronic // By: SERPENT1867 Date: Tue, 5 Nov 2024 18:46:37 +0100 Subject: [PATCH 13/46] Update Fps-returne.js --- extensions/Eaielectronic/Fps-returne.js | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/Eaielectronic/Fps-returne.js b/extensions/Eaielectronic/Fps-returne.js index 958a145341..b082e152e6 100644 --- a/extensions/Eaielectronic/Fps-returne.js +++ b/extensions/Eaielectronic/Fps-returne.js @@ -1,6 +1,7 @@ // Name: FPS returne // ID: fpsbasedreturn // Description: allows you to create games that run at the same speed, even if the FPS changes. +// By: Eaielectronic // By: SERPENT1867 // License: MPL-2.0 class FPSBasedReturn { From fc3218e9b87d7d596ca22a7910526ab6e097d924 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:46:49 +0100 Subject: [PATCH 14/46] Update Login-page.js --- extensions/Eaielectronic/Login-page.js | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/Eaielectronic/Login-page.js b/extensions/Eaielectronic/Login-page.js index 7c01711070..bde04d0915 100644 --- a/extensions/Eaielectronic/Login-page.js +++ b/extensions/Eaielectronic/Login-page.js @@ -1,6 +1,7 @@ // Name: Login // ID: usermanagement // Description: Allows you to create login forms. +// By: Eaielectronic // By: SERPENT1867 // License: MPL-2.0 class UserManagement { From 17a62a5ffc6211f8b1f7c953201d804be7f66607 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:47:01 +0100 Subject: [PATCH 15/46] Update ScrollingTextBubble.js --- extensions/Eaielectronic/ScrollingTextBubble.js | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/Eaielectronic/ScrollingTextBubble.js b/extensions/Eaielectronic/ScrollingTextBubble.js index a3b7d10ed2..c581f6389d 100644 --- a/extensions/Eaielectronic/ScrollingTextBubble.js +++ b/extensions/Eaielectronic/ScrollingTextBubble.js @@ -1,6 +1,7 @@ // Name: Scrolling bull // ID: scrollingTextBubble', // Description: Create scrolling text bubbles and apply styles with Html tags. +// By: Eaielectronic // By: SERPENT1867 // License: MPL-2.0 (function(Scratch) { From 34ba4b158d187c2b7f1415f0e6c4f0a2b309c685 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:47:47 +0100 Subject: [PATCH 16/46] Create teste.txt --- images/Eaielectronic/teste.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 images/Eaielectronic/teste.txt diff --git a/images/Eaielectronic/teste.txt b/images/Eaielectronic/teste.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/images/Eaielectronic/teste.txt @@ -0,0 +1 @@ + From 32f7557713492bc9c5626c3017c059d37684eff7 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:55:18 +0100 Subject: [PATCH 17/46] Create teste --- images/Eaielectronic/teste | 1 + 1 file changed, 1 insertion(+) create mode 100644 images/Eaielectronic/teste diff --git a/images/Eaielectronic/teste b/images/Eaielectronic/teste new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/images/Eaielectronic/teste @@ -0,0 +1 @@ + From e8782c442cb3eb7b5b4500ceefdeba424b587d5c Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:55:48 +0100 Subject: [PATCH 18/46] Add files via upload --- images/Eaielectronic/Finger-mutli-mobile.svg | 1 + images/Eaielectronic/Finger-mutli-mobile2.svg | 1 + images/Eaielectronic/ScrollingTextBubble.js.svg | 1 + 3 files changed, 3 insertions(+) create mode 100644 images/Eaielectronic/Finger-mutli-mobile.svg create mode 100644 images/Eaielectronic/Finger-mutli-mobile2.svg create mode 100644 images/Eaielectronic/ScrollingTextBubble.js.svg diff --git a/images/Eaielectronic/Finger-mutli-mobile.svg b/images/Eaielectronic/Finger-mutli-mobile.svg new file mode 100644 index 0000000000..973db78e7c --- /dev/null +++ b/images/Eaielectronic/Finger-mutli-mobile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/Eaielectronic/Finger-mutli-mobile2.svg b/images/Eaielectronic/Finger-mutli-mobile2.svg new file mode 100644 index 0000000000..d9fa106b8a --- /dev/null +++ b/images/Eaielectronic/Finger-mutli-mobile2.svg @@ -0,0 +1 @@ +HTML ?<em>YES<em/>YES \ No newline at end of file diff --git a/images/Eaielectronic/ScrollingTextBubble.js.svg b/images/Eaielectronic/ScrollingTextBubble.js.svg new file mode 100644 index 0000000000..d9fa106b8a --- /dev/null +++ b/images/Eaielectronic/ScrollingTextBubble.js.svg @@ -0,0 +1 @@ +HTML ?<em>YES<em/>YES \ No newline at end of file From c7d180d7d730a242dcbb725ec58f1f7b0cb3e517 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:56:20 +0100 Subject: [PATCH 19/46] Delete images/Eaielectronic/Finger-mutli-mobile.svg --- images/Eaielectronic/Finger-mutli-mobile.svg | 1 - 1 file changed, 1 deletion(-) delete mode 100644 images/Eaielectronic/Finger-mutli-mobile.svg diff --git a/images/Eaielectronic/Finger-mutli-mobile.svg b/images/Eaielectronic/Finger-mutli-mobile.svg deleted file mode 100644 index 973db78e7c..0000000000 --- a/images/Eaielectronic/Finger-mutli-mobile.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 211311da0aa6cdd769b4d8355b336cd1933f2a1b Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:56:34 +0100 Subject: [PATCH 20/46] Delete images/Eaielectronic/Finger-mutli-mobile2.svg --- images/Eaielectronic/Finger-mutli-mobile2.svg | 1 - 1 file changed, 1 deletion(-) delete mode 100644 images/Eaielectronic/Finger-mutli-mobile2.svg diff --git a/images/Eaielectronic/Finger-mutli-mobile2.svg b/images/Eaielectronic/Finger-mutli-mobile2.svg deleted file mode 100644 index d9fa106b8a..0000000000 --- a/images/Eaielectronic/Finger-mutli-mobile2.svg +++ /dev/null @@ -1 +0,0 @@ -HTML ?<em>YES<em/>YES \ No newline at end of file From 09d0c3e48d22a0e8e220cbcfa431aedd11a27c0a Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:56:45 +0100 Subject: [PATCH 21/46] Delete images/Eaielectronic/teste --- images/Eaielectronic/teste | 1 - 1 file changed, 1 deletion(-) delete mode 100644 images/Eaielectronic/teste diff --git a/images/Eaielectronic/teste b/images/Eaielectronic/teste deleted file mode 100644 index 8b13789179..0000000000 --- a/images/Eaielectronic/teste +++ /dev/null @@ -1 +0,0 @@ - From a0e03c0dc49ad203e23319e7f309bd5e4972c363 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:56:52 +0100 Subject: [PATCH 22/46] Delete images/Eaielectronic/teste.txt --- images/Eaielectronic/teste.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 images/Eaielectronic/teste.txt diff --git a/images/Eaielectronic/teste.txt b/images/Eaielectronic/teste.txt deleted file mode 100644 index 8b13789179..0000000000 --- a/images/Eaielectronic/teste.txt +++ /dev/null @@ -1 +0,0 @@ - From 3907f16941c6976c1155d85dd3ad52ef4e639de0 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:57:06 +0100 Subject: [PATCH 23/46] Add files via upload --- images/Eaielectronic/Finger-mutli-mobile.svg | 1 + images/Eaielectronic/Finger-mutli-mobile2.svg | 1 + 2 files changed, 2 insertions(+) create mode 100644 images/Eaielectronic/Finger-mutli-mobile.svg create mode 100644 images/Eaielectronic/Finger-mutli-mobile2.svg diff --git a/images/Eaielectronic/Finger-mutli-mobile.svg b/images/Eaielectronic/Finger-mutli-mobile.svg new file mode 100644 index 0000000000..79f91f2ffb --- /dev/null +++ b/images/Eaielectronic/Finger-mutli-mobile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/Eaielectronic/Finger-mutli-mobile2.svg b/images/Eaielectronic/Finger-mutli-mobile2.svg new file mode 100644 index 0000000000..d9fa106b8a --- /dev/null +++ b/images/Eaielectronic/Finger-mutli-mobile2.svg @@ -0,0 +1 @@ +HTML ?<em>YES<em/>YES \ No newline at end of file From ae418c5a4f0362f4aaa2e8346f11c5b76a3ae05b Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:57:38 +0100 Subject: [PATCH 24/46] Delete images/Eaielectronic/Finger-mutli-mobile2.svg --- images/Eaielectronic/Finger-mutli-mobile2.svg | 1 - 1 file changed, 1 deletion(-) delete mode 100644 images/Eaielectronic/Finger-mutli-mobile2.svg diff --git a/images/Eaielectronic/Finger-mutli-mobile2.svg b/images/Eaielectronic/Finger-mutli-mobile2.svg deleted file mode 100644 index d9fa106b8a..0000000000 --- a/images/Eaielectronic/Finger-mutli-mobile2.svg +++ /dev/null @@ -1 +0,0 @@ -HTML ?<em>YES<em/>YES \ No newline at end of file From b786216b6b6c9f6ff8b53a5cf69a6084e9641c05 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:58:00 +0100 Subject: [PATCH 25/46] Add files via upload --- images/Eaielectronic/Login-page.svg | 1 + 1 file changed, 1 insertion(+) create mode 100644 images/Eaielectronic/Login-page.svg diff --git a/images/Eaielectronic/Login-page.svg b/images/Eaielectronic/Login-page.svg new file mode 100644 index 0000000000..65d2427346 --- /dev/null +++ b/images/Eaielectronic/Login-page.svg @@ -0,0 +1 @@ +LoginCancelUserNamePassword \ No newline at end of file From aa36118e4ecc65169fbd59c1393629a3d86fbba4 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:01:58 +0100 Subject: [PATCH 26/46] Update ScrollingTextBubble.js.svg --- images/Eaielectronic/ScrollingTextBubble.js.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/Eaielectronic/ScrollingTextBubble.js.svg b/images/Eaielectronic/ScrollingTextBubble.js.svg index d9fa106b8a..b20fe3b3d4 100644 --- a/images/Eaielectronic/ScrollingTextBubble.js.svg +++ b/images/Eaielectronic/ScrollingTextBubble.js.svg @@ -1 +1 @@ -HTML ?<em>YES<em/>YES \ No newline at end of file +HTML ?<em>YES<em/>YES From d6f8ba391b63ac71133337e62890235cf9c30bcb Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:02:31 +0100 Subject: [PATCH 27/46] Update Login-page.svg --- images/Eaielectronic/Login-page.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/Eaielectronic/Login-page.svg b/images/Eaielectronic/Login-page.svg index 65d2427346..222de73b4e 100644 --- a/images/Eaielectronic/Login-page.svg +++ b/images/Eaielectronic/Login-page.svg @@ -1 +1 @@ -LoginCancelUserNamePassword \ No newline at end of file +LoginCancelUserNamePassword From 84f3ba243ee4f1c9cb091ed8a887f99b2ab92c0c Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:03:06 +0100 Subject: [PATCH 28/46] Update Finger-mutli-mobile.svg --- images/Eaielectronic/Finger-mutli-mobile.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/Eaielectronic/Finger-mutli-mobile.svg b/images/Eaielectronic/Finger-mutli-mobile.svg index 79f91f2ffb..b2cdbbc5fc 100644 --- a/images/Eaielectronic/Finger-mutli-mobile.svg +++ b/images/Eaielectronic/Finger-mutli-mobile.svg @@ -1 +1 @@ - \ No newline at end of file + From a60c18ce47fca1f331f8a30e89477f16d3172a9f Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:21:42 +0100 Subject: [PATCH 29/46] Delete images/Eaielectronic/ScrollingTextBubble.js.svg --- images/Eaielectronic/ScrollingTextBubble.js.svg | 1 - 1 file changed, 1 deletion(-) delete mode 100644 images/Eaielectronic/ScrollingTextBubble.js.svg diff --git a/images/Eaielectronic/ScrollingTextBubble.js.svg b/images/Eaielectronic/ScrollingTextBubble.js.svg deleted file mode 100644 index b20fe3b3d4..0000000000 --- a/images/Eaielectronic/ScrollingTextBubble.js.svg +++ /dev/null @@ -1 +0,0 @@ -HTML ?<em>YES<em/>YES From acf692050e2c7370ea68acd45031dd990f1741c6 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:21:56 +0100 Subject: [PATCH 30/46] Delete images/Eaielectronic/Login-page.svg --- images/Eaielectronic/Login-page.svg | 1 - 1 file changed, 1 deletion(-) delete mode 100644 images/Eaielectronic/Login-page.svg diff --git a/images/Eaielectronic/Login-page.svg b/images/Eaielectronic/Login-page.svg deleted file mode 100644 index 222de73b4e..0000000000 --- a/images/Eaielectronic/Login-page.svg +++ /dev/null @@ -1 +0,0 @@ -LoginCancelUserNamePassword From b4151aa192ecae597b1c67c1c48f47ccf122c12e Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:22:26 +0100 Subject: [PATCH 31/46] Add files via upload --- images/Eaielectronic/Login-page 2.svg | 1 + images/Eaielectronic/ScrollingTextBubble.svg | 1 + 2 files changed, 2 insertions(+) create mode 100644 images/Eaielectronic/Login-page 2.svg create mode 100644 images/Eaielectronic/ScrollingTextBubble.svg diff --git a/images/Eaielectronic/Login-page 2.svg b/images/Eaielectronic/Login-page 2.svg new file mode 100644 index 0000000000..1200b23acb --- /dev/null +++ b/images/Eaielectronic/Login-page 2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/Eaielectronic/ScrollingTextBubble.svg b/images/Eaielectronic/ScrollingTextBubble.svg new file mode 100644 index 0000000000..3d1777a899 --- /dev/null +++ b/images/Eaielectronic/ScrollingTextBubble.svg @@ -0,0 +1 @@ + \ No newline at end of file From f4531fc5e313110ef5d9339951e826aab24c2861 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:37:39 +0100 Subject: [PATCH 32/46] Update Fps-returne.js --- extensions/Eaielectronic/Fps-returne.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extensions/Eaielectronic/Fps-returne.js b/extensions/Eaielectronic/Fps-returne.js index b082e152e6..b4938cc192 100644 --- a/extensions/Eaielectronic/Fps-returne.js +++ b/extensions/Eaielectronic/Fps-returne.js @@ -4,6 +4,8 @@ // By: Eaielectronic // By: SERPENT1867 // License: MPL-2.0 +(function (Scratch) { + "use strict"; class FPSBasedReturn { constructor() { this.previousTime = null; // Pour stocker l'heure de la dernière frame @@ -72,3 +74,4 @@ class FPSBasedReturn { // Enregistrer l'extension dans TurboWarp Scratch.extensions.register(new FPSBasedReturn()); + })(Scratch); From bdb3d5d8052512e2f7e7e3cf3e60d317e1d4ac0d Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:39:07 +0100 Subject: [PATCH 33/46] Update Login-page.js --- extensions/Eaielectronic/Login-page.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extensions/Eaielectronic/Login-page.js b/extensions/Eaielectronic/Login-page.js index bde04d0915..3175a6a9cb 100644 --- a/extensions/Eaielectronic/Login-page.js +++ b/extensions/Eaielectronic/Login-page.js @@ -4,6 +4,8 @@ // By: Eaielectronic // By: SERPENT1867 // License: MPL-2.0 +(function (Scratch) { + "use strict"; class UserManagement { constructor() { this.users = []; @@ -254,4 +256,5 @@ class UserManagement { } Scratch.extensions.register(new UserManagement()); +})(Scratch); From b2a48bc54a04d9e593bcff0d285568bd63567f4e Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:50:38 +0100 Subject: [PATCH 34/46] Update ScrollingTextBubble.js --- extensions/Eaielectronic/ScrollingTextBubble.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/extensions/Eaielectronic/ScrollingTextBubble.js b/extensions/Eaielectronic/ScrollingTextBubble.js index c581f6389d..7999d60d33 100644 --- a/extensions/Eaielectronic/ScrollingTextBubble.js +++ b/extensions/Eaielectronic/ScrollingTextBubble.js @@ -4,6 +4,8 @@ // By: Eaielectronic // By: SERPENT1867 // License: MPL-2.0 +(function(Scratch) { + 'use strict'; (function(Scratch) { 'use strict'; @@ -191,7 +193,7 @@ hideAllTextBubbles() { for (const spriteId in this.bubbles) { - if (this.bubbles.hasOwnProperty(spriteId)) { + if (Object.prototype.hasOwnProperty.call(this.bubbles, spriteId)) { clearInterval(this.bubbles[spriteId].intervalId); this.bubbles[spriteId].bubbleDiv.remove(); delete this.bubbles[spriteId]; @@ -274,3 +276,5 @@ Scratch.extensions.register(new ScrollingTextBubble()); })(Scratch); + +})(Scratch); From 77cc15c285807a302297fb1cbd47548d02fb8f2f Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:53:51 +0100 Subject: [PATCH 35/46] Update ScrollingTextBubble.js --- extensions/Eaielectronic/ScrollingTextBubble.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/extensions/Eaielectronic/ScrollingTextBubble.js b/extensions/Eaielectronic/ScrollingTextBubble.js index 7999d60d33..fe4a0f8247 100644 --- a/extensions/Eaielectronic/ScrollingTextBubble.js +++ b/extensions/Eaielectronic/ScrollingTextBubble.js @@ -4,8 +4,6 @@ // By: Eaielectronic // By: SERPENT1867 // License: MPL-2.0 -(function(Scratch) { - 'use strict'; (function(Scratch) { 'use strict'; @@ -276,5 +274,3 @@ Scratch.extensions.register(new ScrollingTextBubble()); })(Scratch); - -})(Scratch); From c9d1d4d32feaf343aff6fe6e2499cbdfeafd22b9 Mon Sep 17 00:00:00 2001 From: Eaielectronic <164761054+Eaielectronic@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:58:47 +0100 Subject: [PATCH 36/46] Update ScrollingTextBubble.js --- extensions/Eaielectronic/ScrollingTextBubble.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/Eaielectronic/ScrollingTextBubble.js b/extensions/Eaielectronic/ScrollingTextBubble.js index fe4a0f8247..befd755f7c 100644 --- a/extensions/Eaielectronic/ScrollingTextBubble.js +++ b/extensions/Eaielectronic/ScrollingTextBubble.js @@ -1,5 +1,5 @@ // Name: Scrolling bull -// ID: scrollingTextBubble', +// ID: scrollingTextBubble // Description: Create scrolling text bubbles and apply styles with Html tags. // By: Eaielectronic // By: SERPENT1867 From 5b74dc3991243ab55427671347cbdb22a6b6ede9 Mon Sep 17 00:00:00 2001 From: Eaielectronic <06diodeled@gmail.com> Date: Wed, 6 Nov 2024 17:21:30 +0100 Subject: [PATCH 37/46] apply prettier --- .../Eaielectronic/Finger-mutli-mobile.js | 284 ++++++----- extensions/Eaielectronic/Fps-returne.js | 94 ++-- extensions/Eaielectronic/Login-page.js | 461 ++++++++--------- .../Eaielectronic/ScrollingTextBubble.js | 474 +++++++++--------- 4 files changed, 668 insertions(+), 645 deletions(-) diff --git a/extensions/Eaielectronic/Finger-mutli-mobile.js b/extensions/Eaielectronic/Finger-mutli-mobile.js index 8a49a26478..311a103acb 100644 --- a/extensions/Eaielectronic/Finger-mutli-mobile.js +++ b/extensions/Eaielectronic/Finger-mutli-mobile.js @@ -5,156 +5,168 @@ // By: SERPENT1867 { - const canvas = Scratch.renderer.canvas; // Récupère le canvas de Scratch - const rect = canvas.getBoundingClientRect(); // Récupère la position du canvas - const scratchX = ((touch.clientX - rect.left) / rect.width) * 480 - 240; - const scratchY = 180 - ((touch.clientY - rect.top) / rect.height) * 360; - return { x: scratchX, y: scratchY }; - }; - - const touchHandler = (event) => { - // Met à jour les coordonnées des doigts dans le tableau - for (let i = 0; i < event.touches.length && i < 10; i++) { - const touch = event.touches[i]; - const { x, y } = convertToScratchCoords(touch); - this.touches[i] = { x, y }; - } - - // Réinitialise les positions restantes si moins de doigts - for (let i = event.touches.length; i < 10; i++) { - this.touches[i] = { x: 0, y: 0 }; - } - }; - - window.addEventListener('touchstart', touchHandler); - window.addEventListener('touchmove', touchHandler); - window.addEventListener('touchend', touchHandler); + // Fonction qui configure les écouteurs d'événements tactiles + setupTouchListeners() { + const convertToScratchCoords = (touch) => { + const canvas = Scratch.renderer.canvas; // Récupère le canvas de Scratch + const rect = canvas.getBoundingClientRect(); // Récupère la position du canvas + const scratchX = ((touch.clientX - rect.left) / rect.width) * 480 - 240; + const scratchY = 180 - ((touch.clientY - rect.top) / rect.height) * 360; + return { x: scratchX, y: scratchY }; + }; + + const touchHandler = (event) => { + // Met à jour les coordonnées des doigts dans le tableau + for (let i = 0; i < event.touches.length && i < 10; i++) { + const touch = event.touches[i]; + const { x, y } = convertToScratchCoords(touch); + this.touches[i] = { x, y }; } - // Obtenir la position X du toucher d'un doigt donné - getTouchX(args) { - const index = Math.max(0, Math.min(9, args.INDEX - 1)); // Limite à 10 doigts - return this.touches[index].x; + // Réinitialise les positions restantes si moins de doigts + for (let i = event.touches.length; i < 10; i++) { + this.touches[i] = { x: 0, y: 0 }; } + }; - // Obtenir la position Y du toucher d'un doigt donné - getTouchY(args) { - const index = Math.max(0, Math.min(9, args.INDEX - 1)); // Limite à 10 doigts - return this.touches[index].y; - } + window.addEventListener("touchstart", touchHandler); + window.addEventListener("touchmove", touchHandler); + window.addEventListener("touchend", touchHandler); + } + + // Obtenir la position X du toucher d'un doigt donné + getTouchX(args) { + const index = Math.max(0, Math.min(9, args.INDEX - 1)); // Limite à 10 doigts + return this.touches[index].x; + } - // Nouveau: Obtenir la position X d'un doigt touchant un sprite - getTouchXOnSprite(args, util) { - const spriteBounds = util.target.getBounds(); - - // Cherche le premier doigt touchant le sprite et renvoie sa position X - for (let i = 0; i < this.touches.length; i++) { - const touch = this.touches[i]; - if (spriteBounds.left <= touch.x && touch.x <= spriteBounds.right && - spriteBounds.bottom <= touch.y && touch.y <= spriteBounds.top) { - return touch.x; - } - } - return 0; // Retourne 0 si aucun doigt ne touche le sprite + // Obtenir la position Y du toucher d'un doigt donné + getTouchY(args) { + const index = Math.max(0, Math.min(9, args.INDEX - 1)); // Limite à 10 doigts + return this.touches[index].y; + } + + // Nouveau: Obtenir la position X d'un doigt touchant un sprite + getTouchXOnSprite(args, util) { + const spriteBounds = util.target.getBounds(); + + // Cherche le premier doigt touchant le sprite et renvoie sa position X + for (let i = 0; i < this.touches.length; i++) { + const touch = this.touches[i]; + if ( + spriteBounds.left <= touch.x && + touch.x <= spriteBounds.right && + spriteBounds.bottom <= touch.y && + touch.y <= spriteBounds.top + ) { + return touch.x; } + } + return 0; // Retourne 0 si aucun doigt ne touche le sprite + } - // Nouveau: Obtenir la position Y d'un doigt touchant un sprite - getTouchYOnSprite(args, util) { - const spriteBounds = util.target.getBounds(); - - // Cherche le premier doigt touchant le sprite et renvoie sa position Y - for (let i = 0; i < this.touches.length; i++) { - const touch = this.touches[i]; - if (spriteBounds.left <= touch.x && touch.x <= spriteBounds.right && - spriteBounds.bottom <= touch.y && touch.y <= spriteBounds.top) { - return touch.y; - } - } - return 0; // Retourne 0 si aucun doigt ne touche le sprite + // Nouveau: Obtenir la position Y d'un doigt touchant un sprite + getTouchYOnSprite(args, util) { + const spriteBounds = util.target.getBounds(); + + // Cherche le premier doigt touchant le sprite et renvoie sa position Y + for (let i = 0; i < this.touches.length; i++) { + const touch = this.touches[i]; + if ( + spriteBounds.left <= touch.x && + touch.x <= spriteBounds.right && + spriteBounds.bottom <= touch.y && + touch.y <= spriteBounds.top + ) { + return touch.y; } + } + return 0; // Retourne 0 si aucun doigt ne touche le sprite } + } - Scratch.extensions.register(new MultiTouchDetection()); + Scratch.extensions.register(new MultiTouchDetection()); })(Scratch); diff --git a/extensions/Eaielectronic/Fps-returne.js b/extensions/Eaielectronic/Fps-returne.js index b4938cc192..2d7ce09a71 100644 --- a/extensions/Eaielectronic/Fps-returne.js +++ b/extensions/Eaielectronic/Fps-returne.js @@ -5,73 +5,73 @@ // By: SERPENT1867 // License: MPL-2.0 (function (Scratch) { - "use strict"; -class FPSBasedReturn { + "use strict"; + class FPSBasedReturn { constructor() { - this.previousTime = null; // Pour stocker l'heure de la dernière frame - this.fpsValue = 30; // Initialiser avec une valeur par défaut (30 FPS) + this.previousTime = null; // Pour stocker l'heure de la dernière frame + this.fpsValue = 30; // Initialiser avec une valeur par défaut (30 FPS) } getInfo() { - return { - id: 'fpsbasedreturn', - name: 'FPS Based Return', - blocks: [ - { - opcode: 'getFPSMultiplier', - blockType: Scratch.BlockType.REPORTER, - text: 'FPS multiplier (based on [REFERENCE] FPS', - arguments: { - REFERENCE: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 30 - } - } - }, - { - opcode: 'getCurrentFPS', - blockType: Scratch.BlockType.REPORTER, - text: 'current FPS' - } - ] - }; + return { + id: "fpsbasedreturn", + name: "FPS Based Return", + blocks: [ + { + opcode: "getFPSMultiplier", + blockType: Scratch.BlockType.REPORTER, + text: "FPS multiplier (based on [REFERENCE] FPS", + arguments: { + REFERENCE: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 30, + }, + }, + }, + { + opcode: "getCurrentFPS", + blockType: Scratch.BlockType.REPORTER, + text: "current FPS", + }, + ], + }; } // Méthode pour obtenir le delta time et calculer une fois les FPS calculateFPS() { - const currentTime = performance.now(); + const currentTime = performance.now(); - if (this.previousTime === null) { - this.previousTime = currentTime; - return; // Attendre jusqu'à la prochaine frame pour calculer le delta time - } - - let deltaTime = (currentTime - this.previousTime) / 1000; // Convertir en secondes + if (this.previousTime === null) { this.previousTime = currentTime; + return; // Attendre jusqu'à la prochaine frame pour calculer le delta time + } + + let deltaTime = (currentTime - this.previousTime) / 1000; // Convertir en secondes + this.previousTime = currentTime; - if (deltaTime > 1/30) { - deltaTime = 1/30; // Limiter à 30 FPS max pour éviter des pics - } + if (deltaTime > 1 / 30) { + deltaTime = 1 / 30; // Limiter à 30 FPS max pour éviter des pics + } - this.fpsValue = 1 / deltaTime; // Calculer les FPS actuels + this.fpsValue = 1 / deltaTime; // Calculer les FPS actuels } // Méthode pour retourner le FPS actuel getCurrentFPS() { - this.calculateFPS(); // Mettre à jour le FPS - return this.fpsValue; // Retourner la valeur des FPS actuels + this.calculateFPS(); // Mettre à jour le FPS + return this.fpsValue; // Retourner la valeur des FPS actuels } // Méthode pour calculer le multiplicateur en fonction des FPS getFPSMultiplier(args) { - const referenceFPS = args.REFERENCE; // FPS de référence choisi par l'utilisateur - const fps = this.getCurrentFPS(); // Obtenir les FPS actuels + const referenceFPS = args.REFERENCE; // FPS de référence choisi par l'utilisateur + const fps = this.getCurrentFPS(); // Obtenir les FPS actuels - const multiplier = referenceFPS / fps; // Le rapport par rapport au FPS de référence - return multiplier; + const multiplier = referenceFPS / fps; // Le rapport par rapport au FPS de référence + return multiplier; } -} + } -// Enregistrer l'extension dans TurboWarp -Scratch.extensions.register(new FPSBasedReturn()); - })(Scratch); + // Enregistrer l'extension dans TurboWarp + Scratch.extensions.register(new FPSBasedReturn()); +})(Scratch); diff --git a/extensions/Eaielectronic/Login-page.js b/extensions/Eaielectronic/Login-page.js index 3175a6a9cb..0caa5663f3 100644 --- a/extensions/Eaielectronic/Login-page.js +++ b/extensions/Eaielectronic/Login-page.js @@ -5,256 +5,267 @@ // By: SERPENT1867 // License: MPL-2.0 (function (Scratch) { - "use strict"; -class UserManagement { + "use strict"; + class UserManagement { constructor() { - this.users = []; - this.username = ''; - this.password = ''; - this.email = ''; - this.turbowarp = ''; // Variable for the form state + this.users = []; + this.username = ""; + this.password = ""; + this.email = ""; + this.turbowarp = ""; // Variable for the form state } - + getInfo() { - return { - id: 'usermanagement', - name: 'User Management', - color1: '#ff3f00', // Slightly darker blue - blocks: [ - { - opcode: 'openForm', - blockType: Scratch.BlockType.COMMAND, - text: 'open form for [ACTION]', - arguments: { - ACTION: { - type: Scratch.ArgumentType.STRING, - menu: 'actionsMenu', - defaultValue: 'login' - } - } - }, - { - opcode: 'hideForm', - blockType: Scratch.BlockType.COMMAND, - text: 'hide form', - }, - { - opcode: 'getUsername', - blockType: Scratch.BlockType.REPORTER, - text: 'username', - }, - { - opcode: 'getPassword', - blockType: Scratch.BlockType.REPORTER, - text: 'password', - }, - { - opcode: 'getEmail', - blockType: Scratch.BlockType.REPORTER, - text: 'email', - }, - { - opcode: 'getFormState', - blockType: Scratch.BlockType.REPORTER, - text: 'form state', - }, - { - opcode: 'clear', - blockType: Scratch.BlockType.COMMAND, - text: 'clear values', - } - ], - menus: { - actionsMenu: { - items: ['login', 'create account', 'recover password'] - } - } - }; + return { + id: "usermanagement", + name: "User Management", + color1: "#ff3f00", // Slightly darker blue + blocks: [ + { + opcode: "openForm", + blockType: Scratch.BlockType.COMMAND, + text: "open form for [ACTION]", + arguments: { + ACTION: { + type: Scratch.ArgumentType.STRING, + menu: "actionsMenu", + defaultValue: "login", + }, + }, + }, + { + opcode: "hideForm", + blockType: Scratch.BlockType.COMMAND, + text: "hide form", + }, + { + opcode: "getUsername", + blockType: Scratch.BlockType.REPORTER, + text: "username", + }, + { + opcode: "getPassword", + blockType: Scratch.BlockType.REPORTER, + text: "password", + }, + { + opcode: "getEmail", + blockType: Scratch.BlockType.REPORTER, + text: "email", + }, + { + opcode: "getFormState", + blockType: Scratch.BlockType.REPORTER, + text: "form state", + }, + { + opcode: "clear", + blockType: Scratch.BlockType.COMMAND, + text: "clear values", + }, + ], + menus: { + actionsMenu: { + items: ["login", "create account", "recover password"], + }, + }, + }; } - + openForm(args) { - const { ACTION } = args; - this.turbowarp = ACTION; // Update the form state - this.hideForm(false); // Hide the previous form if open - - const form = document.createElement('form'); - form.style.position = 'absolute'; - form.style.top = '50%'; - form.style.left = '50%'; - form.style.transform = 'translate(-50%, -50%)'; - form.style.padding = '20px'; - form.style.backgroundColor = '#f9f9f9'; - form.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)'; - form.style.borderRadius = '8px'; - form.style.width = '300px'; - form.style.fontFamily = 'Arial, sans-serif'; - - const closeButton = document.createElement('span'); - closeButton.textContent = '✖'; - closeButton.style.position = 'absolute'; - closeButton.style.top = '10px'; - closeButton.style.right = '10px'; - closeButton.style.cursor = 'pointer'; - closeButton.style.color = '#000'; - closeButton.addEventListener('click', () => { - this.hideForm(); - }); - form.appendChild(closeButton); - - const title = document.createElement('h2'); - title.textContent = ACTION.charAt(0).toUpperCase() + ACTION.slice(1); - title.style.textAlign = 'center'; - title.style.color = '#333'; - form.appendChild(title); - - if (ACTION === 'login' || ACTION === 'create account') { - const usernameInput = document.createElement('input'); - usernameInput.type = 'text'; - usernameInput.name = 'username'; - usernameInput.placeholder = 'Username'; - usernameInput.style.width = '90%'; - usernameInput.style.padding = '10px'; - usernameInput.style.margin = '10px 0'; - usernameInput.style.border = '1px solid #ccc'; - usernameInput.style.borderRadius = '4px'; - form.appendChild(usernameInput); - - const passwordInput = document.createElement('input'); - passwordInput.type = 'password'; - passwordInput.name = 'password'; - passwordInput.placeholder = 'Password'; - passwordInput.style.width = '90%'; - passwordInput.style.padding = '10px'; - passwordInput.style.margin = '10px 0'; - passwordInput.style.border = '1px solid #ccc'; - passwordInput.style.borderRadius = '4px'; - form.appendChild(passwordInput); + const { ACTION } = args; + this.turbowarp = ACTION; // Update the form state + this.hideForm(false); // Hide the previous form if open + + const form = document.createElement("form"); + form.style.position = "absolute"; + form.style.top = "50%"; + form.style.left = "50%"; + form.style.transform = "translate(-50%, -50%)"; + form.style.padding = "20px"; + form.style.backgroundColor = "#f9f9f9"; + form.style.boxShadow = "0 0 10px rgba(0, 0, 0, 0.1)"; + form.style.borderRadius = "8px"; + form.style.width = "300px"; + form.style.fontFamily = "Arial, sans-serif"; + + const closeButton = document.createElement("span"); + closeButton.textContent = "✖"; + closeButton.style.position = "absolute"; + closeButton.style.top = "10px"; + closeButton.style.right = "10px"; + closeButton.style.cursor = "pointer"; + closeButton.style.color = "#000"; + closeButton.addEventListener("click", () => { + this.hideForm(); + }); + form.appendChild(closeButton); + + const title = document.createElement("h2"); + title.textContent = ACTION.charAt(0).toUpperCase() + ACTION.slice(1); + title.style.textAlign = "center"; + title.style.color = "#333"; + form.appendChild(title); + + if (ACTION === "login" || ACTION === "create account") { + const usernameInput = document.createElement("input"); + usernameInput.type = "text"; + usernameInput.name = "username"; + usernameInput.placeholder = "Username"; + usernameInput.style.width = "90%"; + usernameInput.style.padding = "10px"; + usernameInput.style.margin = "10px 0"; + usernameInput.style.border = "1px solid #ccc"; + usernameInput.style.borderRadius = "4px"; + form.appendChild(usernameInput); + + const passwordInput = document.createElement("input"); + passwordInput.type = "password"; + passwordInput.name = "password"; + passwordInput.placeholder = "Password"; + passwordInput.style.width = "90%"; + passwordInput.style.padding = "10px"; + passwordInput.style.margin = "10px 0"; + passwordInput.style.border = "1px solid #ccc"; + passwordInput.style.borderRadius = "4px"; + form.appendChild(passwordInput); + } + + if (ACTION === "create account" || ACTION === "recover password") { + const emailInput = document.createElement("input"); + emailInput.type = "email"; + emailInput.name = "email"; + emailInput.placeholder = "Email"; + emailInput.style.width = "95%"; + emailInput.style.padding = "10px"; + emailInput.style.margin = "10px 0"; + emailInput.style.border = "1px solid #ccc"; + emailInput.style.borderRadius = "4px"; + form.appendChild(emailInput); + } + + const submitButton = document.createElement("button"); + submitButton.type = "submit"; + submitButton.textContent = "Send"; + submitButton.style.width = "100%"; + submitButton.style.padding = "10px"; + submitButton.style.margin = "10px 0"; + submitButton.style.backgroundColor = "#4CAF50"; + submitButton.style.color = "#fff"; + submitButton.style.border = "none"; + submitButton.style.borderRadius = "4px"; + submitButton.style.cursor = "pointer"; + form.appendChild(submitButton); + + const resetPasswordLink = document.createElement("a"); + resetPasswordLink.textContent = "Reset password"; + resetPasswordLink.style.display = "block"; + resetPasswordLink.style.textAlign = "center"; + resetPasswordLink.style.marginTop = "10px"; + resetPasswordLink.style.color = "#007BFF"; + resetPasswordLink.style.cursor = "pointer"; + resetPasswordLink.addEventListener("click", () => { + this.hideForm(false); + this.openForm({ ACTION: "recover password" }); + }); + form.appendChild(resetPasswordLink); + + const createAccountLink = document.createElement("a"); + createAccountLink.textContent = "Account creation"; + createAccountLink.style.display = "block"; + createAccountLink.style.textAlign = "center"; + createAccountLink.style.marginTop = "10px"; + createAccountLink.style.color = "#007BFF"; + createAccountLink.style.cursor = "pointer"; + createAccountLink.addEventListener("click", () => { + this.hideForm(false); + this.openForm({ ACTION: "create account" }); + }); + form.appendChild(createAccountLink); + + document.body.appendChild(form); + + form.addEventListener("submit", (event) => { + event.preventDefault(); + const formData = new FormData(form); + this.username = formData.get("username"); + this.password = formData.get("password"); + this.email = formData.get("email"); + + if (ACTION === "login") { + this.login({ USERNAME: this.username, PASSWORD: this.password }); + } else if (ACTION === "create account") { + this.createAccount({ + USERNAME: this.username, + PASSWORD: this.password, + EMAIL: this.email, + }); + } else if (ACTION === "recover password") { + this.recoverPassword({ EMAIL: this.email }); } - - if (ACTION === 'create account' || ACTION === 'recover password') { - const emailInput = document.createElement('input'); - emailInput.type = 'email'; - emailInput.name = 'email'; - emailInput.placeholder = 'Email'; - emailInput.style.width = '95%'; - emailInput.style.padding = '10px'; - emailInput.style.margin = '10px 0'; - emailInput.style.border = '1px solid #ccc'; - emailInput.style.borderRadius = '4px'; - form.appendChild(emailInput); - } - - const submitButton = document.createElement('button'); - submitButton.type = 'submit'; - submitButton.textContent = 'Send'; - submitButton.style.width = '100%'; - submitButton.style.padding = '10px'; - submitButton.style.margin = '10px 0'; - submitButton.style.backgroundColor = '#4CAF50'; - submitButton.style.color = '#fff'; - submitButton.style.border = 'none'; - submitButton.style.borderRadius = '4px'; - submitButton.style.cursor = 'pointer'; - form.appendChild(submitButton); - - const resetPasswordLink = document.createElement('a'); - resetPasswordLink.textContent = 'Reset password'; - resetPasswordLink.style.display = 'block'; - resetPasswordLink.style.textAlign = 'center'; - resetPasswordLink.style.marginTop = '10px'; - resetPasswordLink.style.color = '#007BFF'; - resetPasswordLink.style.cursor = 'pointer'; - resetPasswordLink.addEventListener('click', () => { - this.hideForm(false); - this.openForm({ ACTION: 'recover password' }); - }); - form.appendChild(resetPasswordLink); - - const createAccountLink = document.createElement('a'); - createAccountLink.textContent = 'Account creation'; - createAccountLink.style.display = 'block'; - createAccountLink.style.textAlign = 'center'; - createAccountLink.style.marginTop = '10px'; - createAccountLink.style.color = '#007BFF'; - createAccountLink.style.cursor = 'pointer'; - createAccountLink.addEventListener('click', () => { - this.hideForm(false); - this.openForm({ ACTION: 'create account' }); - }); - form.appendChild(createAccountLink); - - document.body.appendChild(form); - - form.addEventListener('submit', (event) => { - event.preventDefault(); - const formData = new FormData(form); - this.username = formData.get('username'); - this.password = formData.get('password'); - this.email = formData.get('email'); - - if (ACTION === 'login') { - this.login({ USERNAME: this.username, PASSWORD: this.password }); - } else if (ACTION === 'create account') { - this.createAccount({ USERNAME: this.username, PASSWORD: this.password, EMAIL: this.email }); - } else if (ACTION === 'recover password') { - this.recoverPassword({ EMAIL: this.email }); - } - - this.hideForm(false); - }); + + this.hideForm(false); + }); } - + hideForm() { - const form = document.querySelector('form'); - if (form) { - document.body.removeChild(form); - this.turbowarp = ''; // Reset the form state - } + const form = document.querySelector("form"); + if (form) { + document.body.removeChild(form); + this.turbowarp = ""; // Reset the form state + } } - + createAccount(args) { - const { USERNAME, PASSWORD, EMAIL } = args; - const user = { username: USERNAME, password: PASSWORD, email: EMAIL }; - this.users.push(user); - console.log(`Account created for ${USERNAME}`); + const { USERNAME, PASSWORD, EMAIL } = args; + const user = { username: USERNAME, password: PASSWORD, email: EMAIL }; + this.users.push(user); + console.log(`Account created for ${USERNAME}`); } - + login(args) { - const { USERNAME, PASSWORD } = args; - const user = this.users.find(u => u.username === USERNAME && u.password === PASSWORD); - console.log(user ? `Login successful for ${USERNAME}` : 'Incorrect username or password.'); + const { USERNAME, PASSWORD } = args; + const user = this.users.find( + (u) => u.username === USERNAME && u.password === PASSWORD + ); + console.log( + user + ? `Login successful for ${USERNAME}` + : "Incorrect username or password." + ); } - + recoverPassword(args) { - const { EMAIL } = args; - const user = this.users.find(u => u.email === EMAIL); - console.log(user ? `Your password is: ${user.password}` : 'Email not found.'); + const { EMAIL } = args; + const user = this.users.find((u) => u.email === EMAIL); + console.log( + user ? `Your password is: ${user.password}` : "Email not found." + ); } - + getUsername() { - return this.username; + return this.username; } - + getPassword() { - return this.password; + return this.password; } - + getEmail() { - return this.email; + return this.email; } - + getFormState() { - return this.turbowarp; + return this.turbowarp; } - + clear() { - this.username = ''; - this.password = ''; - this.email = ''; - console.log('Values have been cleared.'); + this.username = ""; + this.password = ""; + this.email = ""; + console.log("Values have been cleared."); } } - + Scratch.extensions.register(new UserManagement()); })(Scratch); - diff --git a/extensions/Eaielectronic/ScrollingTextBubble.js b/extensions/Eaielectronic/ScrollingTextBubble.js index befd755f7c..2442876a6b 100644 --- a/extensions/Eaielectronic/ScrollingTextBubble.js +++ b/extensions/Eaielectronic/ScrollingTextBubble.js @@ -4,273 +4,273 @@ // By: Eaielectronic // By: SERPENT1867 // License: MPL-2.0 -(function(Scratch) { - 'use strict'; +(function (Scratch) { + "use strict"; - class ScrollingTextBubble { - constructor() { - this.bubbles = {}; - this.defaultBubbleStyle = { - backgroundColor: 'rgba(255, 255, 255, 0.8)', - borderColor: 'black', - borderWidth: '2px', - borderRadius: '10px', - boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', - padding: '15px' // Valeur par défaut du padding - }; - } - - getInfo() { - return { - id: 'scrollingTextBubble', - name: 'Scrolling Text Bubble', - blocks: [ - { - opcode: 'showTextBubble', - blockType: Scratch.BlockType.COMMAND, - text: 'show text bubble with text [TEXT] next to sprite with speed [SPEED], font [FONT], width [WIDTH], offsetX [OFFSETX], offsetY [OFFSETY]', - arguments: { - TEXT: { - type: Scratch.ArgumentType.STRING, - defaultValue: 'Hello, World!' - }, - SPEED: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 50 - }, - FONT: { - type: Scratch.ArgumentType.STRING, - defaultValue: 'Arial' - }, - WIDTH: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 200 - }, - OFFSETX: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 0 - }, - OFFSETY: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: -60 - } - }, - filter: [Scratch.TargetType.SPRITE] - }, - { - opcode: 'hideTextBubble', - blockType: Scratch.BlockType.COMMAND, - text: 'hide text bubble', - filter: [Scratch.TargetType.SPRITE] - }, - { - opcode: 'hideAllTextBubbles', - blockType: Scratch.BlockType.COMMAND, - text: 'hide all text bubbles' - }, - { - opcode: 'setBubbleColor', - blockType: Scratch.BlockType.COMMAND, - text: 'set bubble color to [COLOR]', - arguments: { - COLOR: { - type: Scratch.ArgumentType.COLOR, - defaultValue: '#ffffff' - } - } - }, - { - opcode: 'setBubbleStyle', - blockType: Scratch.BlockType.COMMAND, - text: 'set bubble style to [STYLE]', - arguments: { - STYLE: { - type: Scratch.ArgumentType.STRING, - menu: 'bubbleStyleMenu', - defaultValue: 'default' - } - } - }, - { - opcode: 'setBubblePadding', - blockType: Scratch.BlockType.COMMAND, - text: 'set bubble padding to [PADDING]', - arguments: { - PADDING: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 15 // Valeur par défaut pour le padding - } - } - } - ], - menus: { - bubbleStyleMenu: { - acceptReporters: true, - items: ['default', 'rounded', 'sharp', 'shadow', 'no-border'] - } - } - }; - } + class ScrollingTextBubble { + constructor() { + this.bubbles = {}; + this.defaultBubbleStyle = { + backgroundColor: "rgba(255, 255, 255, 0.8)", + borderColor: "black", + borderWidth: "2px", + borderRadius: "10px", + boxShadow: "0 4px 8px rgba(0, 0, 0, 0.2)", + padding: "15px", // Valeur par défaut du padding + }; + } - showTextBubble(args, util) { - const sprite = util.target; - const text = args.TEXT; - const speed = args.SPEED; - const font = args.FONT; - const width = args.WIDTH; - const offsetX = args.OFFSETX; - const offsetY = args.OFFSETY; + getInfo() { + return { + id: "scrollingTextBubble", + name: "Scrolling Text Bubble", + blocks: [ + { + opcode: "showTextBubble", + blockType: Scratch.BlockType.COMMAND, + text: "show text bubble with text [TEXT] next to sprite with speed [SPEED], font [FONT], width [WIDTH], offsetX [OFFSETX], offsetY [OFFSETY]", + arguments: { + TEXT: { + type: Scratch.ArgumentType.STRING, + defaultValue: "Hello, World!", + }, + SPEED: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 50, + }, + FONT: { + type: Scratch.ArgumentType.STRING, + defaultValue: "Arial", + }, + WIDTH: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 200, + }, + OFFSETX: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 0, + }, + OFFSETY: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: -60, + }, + }, + filter: [Scratch.TargetType.SPRITE], + }, + { + opcode: "hideTextBubble", + blockType: Scratch.BlockType.COMMAND, + text: "hide text bubble", + filter: [Scratch.TargetType.SPRITE], + }, + { + opcode: "hideAllTextBubbles", + blockType: Scratch.BlockType.COMMAND, + text: "hide all text bubbles", + }, + { + opcode: "setBubbleColor", + blockType: Scratch.BlockType.COMMAND, + text: "set bubble color to [COLOR]", + arguments: { + COLOR: { + type: Scratch.ArgumentType.COLOR, + defaultValue: "#ffffff", + }, + }, + }, + { + opcode: "setBubbleStyle", + blockType: Scratch.BlockType.COMMAND, + text: "set bubble style to [STYLE]", + arguments: { + STYLE: { + type: Scratch.ArgumentType.STRING, + menu: "bubbleStyleMenu", + defaultValue: "default", + }, + }, + }, + { + opcode: "setBubblePadding", + blockType: Scratch.BlockType.COMMAND, + text: "set bubble padding to [PADDING]", + arguments: { + PADDING: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: 15, // Valeur par défaut pour le padding + }, + }, + }, + ], + menus: { + bubbleStyleMenu: { + acceptReporters: true, + items: ["default", "rounded", "sharp", "shadow", "no-border"], + }, + }, + }; + } - if (this.bubbles[sprite.id]) { - clearInterval(this.bubbles[sprite.id].intervalId); - this.bubbles[sprite.id].bubbleDiv.remove(); - } + showTextBubble(args, util) { + const sprite = util.target; + const text = args.TEXT; + const speed = args.SPEED; + const font = args.FONT; + const width = args.WIDTH; + const offsetX = args.OFFSETX; + const offsetY = args.OFFSETY; - const bubbleDiv = document.createElement('div'); - bubbleDiv.style.position = 'absolute'; - this.applyBubbleStyle(bubbleDiv); - bubbleDiv.style.maxWidth = `${width}px`; - bubbleDiv.style.overflow = 'hidden'; - bubbleDiv.style.whiteSpace = 'pre-wrap'; - bubbleDiv.style.fontFamily = font; - bubbleDiv.style.color = 'black'; - bubbleDiv.style.fontSize = '16px'; - bubbleDiv.style.lineHeight = '1.5'; + if (this.bubbles[sprite.id]) { + clearInterval(this.bubbles[sprite.id].intervalId); + this.bubbles[sprite.id].bubbleDiv.remove(); + } - const canvas = Scratch.renderer.canvas; - const rect = canvas.getBoundingClientRect(); + const bubbleDiv = document.createElement("div"); + bubbleDiv.style.position = "absolute"; + this.applyBubbleStyle(bubbleDiv); + bubbleDiv.style.maxWidth = `${width}px`; + bubbleDiv.style.overflow = "hidden"; + bubbleDiv.style.whiteSpace = "pre-wrap"; + bubbleDiv.style.fontFamily = font; + bubbleDiv.style.color = "black"; + bubbleDiv.style.fontSize = "16px"; + bubbleDiv.style.lineHeight = "1.5"; - const textContainer = document.createElement('span'); - bubbleDiv.appendChild(textContainer); - document.body.appendChild(bubbleDiv); + const canvas = Scratch.renderer.canvas; + const rect = canvas.getBoundingClientRect(); - const updateBubblePosition = () => { - const { x, y } = sprite; + const textContainer = document.createElement("span"); + bubbleDiv.appendChild(textContainer); + document.body.appendChild(bubbleDiv); - const proportionX = rect.width / 480; - const proportionY = rect.height / 360; + const updateBubblePosition = () => { + const { x, y } = sprite; - const adjustedOffsetX = offsetX * proportionX; - const adjustedOffsetY = offsetY * proportionY; + const proportionX = rect.width / 480; + const proportionY = rect.height / 360; - bubbleDiv.style.left = `${rect.left + (x + 240) / 480 * rect.width + adjustedOffsetX}px`; - bubbleDiv.style.top = `${rect.top + (180 - y) / 360 * rect.height + adjustedOffsetY}px`; - }; + const adjustedOffsetX = offsetX * proportionX; + const adjustedOffsetY = offsetY * proportionY; - updateBubblePosition(); - window.addEventListener('mousemove', updateBubblePosition); + bubbleDiv.style.left = `${rect.left + ((x + 240) / 480) * rect.width + adjustedOffsetX}px`; + bubbleDiv.style.top = `${rect.top + ((180 - y) / 360) * rect.height + adjustedOffsetY}px`; + }; - const formattedText = this.formatText(text); - const textParts = this.splitText(formattedText); + updateBubblePosition(); + window.addEventListener("mousemove", updateBubblePosition); - let index = 0; - let currentHTML = ''; + const formattedText = this.formatText(text); + const textParts = this.splitText(formattedText); - const intervalId = setInterval(() => { - if (index < textParts.length) { - currentHTML += textParts[index]; - textContainer.innerHTML = currentHTML; - index++; - } else { - clearInterval(intervalId); - } - }, speed); + let index = 0; + let currentHTML = ""; - this.bubbles[sprite.id] = { intervalId, bubbleDiv }; + const intervalId = setInterval(() => { + if (index < textParts.length) { + currentHTML += textParts[index]; + textContainer.innerHTML = currentHTML; + index++; + } else { + clearInterval(intervalId); } + }, speed); - hideTextBubble(args, util) { - const sprite = util.target; - - if (this.bubbles[sprite.id]) { - clearInterval(this.bubbles[sprite.id].intervalId); - this.bubbles[sprite.id].bubbleDiv.remove(); - delete this.bubbles[sprite.id]; - } - } + this.bubbles[sprite.id] = { intervalId, bubbleDiv }; + } - hideAllTextBubbles() { - for (const spriteId in this.bubbles) { - if (Object.prototype.hasOwnProperty.call(this.bubbles, spriteId)) { - clearInterval(this.bubbles[spriteId].intervalId); - this.bubbles[spriteId].bubbleDiv.remove(); - delete this.bubbles[spriteId]; - } - } - } + hideTextBubble(args, util) { + const sprite = util.target; - setBubbleColor(args) { - const color = args.COLOR; - this.defaultBubbleStyle.backgroundColor = color; - } + if (this.bubbles[sprite.id]) { + clearInterval(this.bubbles[sprite.id].intervalId); + this.bubbles[sprite.id].bubbleDiv.remove(); + delete this.bubbles[sprite.id]; + } + } - setBubblePadding(args) { - const padding = args.PADDING; - this.defaultBubbleStyle.padding = `${padding}px`; + hideAllTextBubbles() { + for (const spriteId in this.bubbles) { + if (Object.prototype.hasOwnProperty.call(this.bubbles, spriteId)) { + clearInterval(this.bubbles[spriteId].intervalId); + this.bubbles[spriteId].bubbleDiv.remove(); + delete this.bubbles[spriteId]; } + } + } - setBubbleStyle(args) { - const style = args.STYLE; + setBubbleColor(args) { + const color = args.COLOR; + this.defaultBubbleStyle.backgroundColor = color; + } - switch (style) { - case 'rounded': - this.defaultBubbleStyle.borderRadius = '20px'; - break; - case 'sharp': - this.defaultBubbleStyle.borderRadius = '0px'; - break; - case 'shadow': - this.defaultBubbleStyle.boxShadow = '0 8px 16px rgba(0, 0, 0, 0.5)'; - break; - case 'no-border': - this.defaultBubbleStyle.borderWidth = '0px'; - break; - default: - this.defaultBubbleStyle = { - backgroundColor: 'rgba(255, 255, 255, 0.8)', - borderColor: 'black', - borderWidth: '2px', - borderRadius: '10px', - boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', - padding: '15px' - }; - break; - } - } + setBubblePadding(args) { + const padding = args.PADDING; + this.defaultBubbleStyle.padding = `${padding}px`; + } - applyBubbleStyle(bubbleDiv) { - bubbleDiv.style.backgroundColor = this.defaultBubbleStyle.backgroundColor; - bubbleDiv.style.border = `${this.defaultBubbleStyle.borderWidth} solid ${this.defaultBubbleStyle.borderColor}`; - bubbleDiv.style.borderRadius = this.defaultBubbleStyle.borderRadius; - bubbleDiv.style.boxShadow = this.defaultBubbleStyle.boxShadow; - bubbleDiv.style.padding = this.defaultBubbleStyle.padding; - } + setBubbleStyle(args) { + const style = args.STYLE; - formatText(text) { - // Retourne le texte brut, seules les balises HTML sont interprétées - return text; - } + switch (style) { + case "rounded": + this.defaultBubbleStyle.borderRadius = "20px"; + break; + case "sharp": + this.defaultBubbleStyle.borderRadius = "0px"; + break; + case "shadow": + this.defaultBubbleStyle.boxShadow = "0 8px 16px rgba(0, 0, 0, 0.5)"; + break; + case "no-border": + this.defaultBubbleStyle.borderWidth = "0px"; + break; + default: + this.defaultBubbleStyle = { + backgroundColor: "rgba(255, 255, 255, 0.8)", + borderColor: "black", + borderWidth: "2px", + borderRadius: "10px", + boxShadow: "0 4px 8px rgba(0, 0, 0, 0.2)", + padding: "15px", + }; + break; + } + } - splitText(text) { - const parts = []; - const tagRegex = /<\/?[^>]+>/g; - let lastIndex = 0; + applyBubbleStyle(bubbleDiv) { + bubbleDiv.style.backgroundColor = this.defaultBubbleStyle.backgroundColor; + bubbleDiv.style.border = `${this.defaultBubbleStyle.borderWidth} solid ${this.defaultBubbleStyle.borderColor}`; + bubbleDiv.style.borderRadius = this.defaultBubbleStyle.borderRadius; + bubbleDiv.style.boxShadow = this.defaultBubbleStyle.boxShadow; + bubbleDiv.style.padding = this.defaultBubbleStyle.padding; + } - text.replace(tagRegex, (match, index) => { - if (index > lastIndex) { - parts.push(...text.slice(lastIndex, index).split('')); - } - parts.push(match); - lastIndex = index + match.length; - }); + formatText(text) { + // Retourne le texte brut, seules les balises HTML sont interprétées + return text; + } - if (lastIndex < text.length) { - parts.push(...text.slice(lastIndex).split('')); - } + splitText(text) { + const parts = []; + const tagRegex = /<\/?[^>]+>/g; + let lastIndex = 0; - return parts; + text.replace(tagRegex, (match, index) => { + if (index > lastIndex) { + parts.push(...text.slice(lastIndex, index).split("")); } + parts.push(match); + lastIndex = index + match.length; + }); + + if (lastIndex < text.length) { + parts.push(...text.slice(lastIndex).split("")); + } + + return parts; } + } - Scratch.extensions.register(new ScrollingTextBubble()); + Scratch.extensions.register(new ScrollingTextBubble()); })(Scratch); From e168e181c5bc1e6abf4b6799e8f9afc7390a7ac3 Mon Sep 17 00:00:00 2001 From: Eaielectronic <06diodeled@gmail.com> Date: Wed, 6 Nov 2024 18:19:47 +0100 Subject: [PATCH 38/46] apply --- development/builder.js | 12 +- development/homepage-template.ejs | 14 +- docs/Xeltalliv/simple3D.md | 1065 -- docs/steamworks.md | 99 - extensions/-SIPC-/consoles.js | 50 +- extensions/-SIPC-/recording.js | 8 +- extensions/-SIPC-/time.js | 2 +- extensions/0832/rxFS.js | 26 +- extensions/0832/rxFS2.js | 22 +- extensions/CST1229/images.js | 8 +- extensions/CST1229/zip.js | 4 - extensions/CubesterYT/KeySimulation.js | 3 +- extensions/CubesterYT/WindowControls.js | 36 +- .../Eaielectronic/Finger-mutli-mobile.js | 172 - extensions/Eaielectronic/Fps-returne.js | 77 - .../Eaielectronic/ScrollingTextBubble.js | 276 - extensions/JeremyGamer13/tween.js | 99 +- extensions/Lily/AllMenus.js | 41 +- extensions/Lily/Assets.js | 8 +- extensions/Lily/ClonesPlus.js | 91 +- extensions/Lily/CommentBlocks.js | 16 +- extensions/Lily/HackedBlocks.js | 2 +- extensions/Lily/ListTools.js | 56 +- extensions/Lily/LooksPlus.js | 112 +- extensions/Lily/McUtils.js | 36 +- extensions/Lily/MoreEvents.js | 76 +- extensions/Lily/MoreTimers.js | 24 +- extensions/Lily/Skins.js | 43 +- extensions/Lily/SoundExpanded.js | 88 +- extensions/Lily/TempVariables.js | 14 +- extensions/Lily/TempVariables2.js | 32 +- extensions/Lily/Video.js | 157 +- extensions/Lily/lmsutils.js | 259 +- extensions/Longboost/color_channels.js | 43 +- extensions/Medericoder/textcase.js | 73 +- extensions/NOname-awa/cn-number.js | 8 +- extensions/NOname-awa/global-coordinate.js | 54 +- extensions/NOname-awa/graphics2d.js | 34 - extensions/NOname-awa/math-and-string.js | 120 +- extensions/NOname-awa/more-comparisons.js | 6 +- extensions/NOname-awa/regular-expression.js | 44 +- extensions/NOname-awa/sort-unique-words.js | 14 +- extensions/NexusKitten/controlcontrols.js | 50 - extensions/NexusKitten/moremotion.js | 3 +- extensions/NexusKitten/sgrab.js | 129 +- extensions/PwLDev/vibration.js | 83 - extensions/SharkPool/Font-Manager.js | 65 +- extensions/Skyhigh173/bigint.js | 2 +- extensions/Skyhigh173/json.js | 16 +- extensions/TheShovel/CanvasEffects.js | 196 +- extensions/TheShovel/ColorPicker.js | 27 +- extensions/TheShovel/CustomStyles.js | 284 +- extensions/TheShovel/LZ-String.js | 38 +- extensions/TheShovel/ShovelUtils.js | 30 +- extensions/TheShovel/profanity.js | 8 +- extensions/TheShovel/profanityAPI.js | 6 +- extensions/WP-Studio01/text2speech.js | 6 +- extensions/Xeltalliv/clippingblending.js | 43 +- extensions/Xeltalliv/simple3D.js | 4972 ---------- extensions/XeroName/Deltatime.js | 14 +- extensions/XmerOriginals/closecontrol.js | 2 +- extensions/ZXMushroom63/searchApi.js | 27 +- extensions/ar.js | 110 +- extensions/bitwise.js | 38 +- extensions/cloudlink.js | 193 +- extensions/codeGIO/ExtraUtilities.js | 58 +- extensions/cs2627883/numericalencoding.js | 4 +- extensions/encoding.js | 30 +- extensions/extensions.json | 4 - extensions/files.js | 9 +- extensions/gamejolt.js | 126 +- extensions/godslayerakp/http.js | 63 +- extensions/godslayerakp/ws.js | 34 +- extensions/itchio.js | 34 +- extensions/lab/text.js | 46 - extensions/mbw/xml.js | 113 +- extensions/mdwalters/notifications.js | 22 +- extensions/obviousAlexC/SensingPlus.js | 8 +- extensions/obviousAlexC/newgroundsIO.js | 96 +- extensions/obviousAlexC/penPlus.js | 7118 ++++---------- extensions/penplus.js | 4 +- extensions/qxsck/data-analysis.js | 2 +- extensions/qxsck/var-and-list.js | 2 +- extensions/rixxyx.js | 62 +- extensions/shreder95ua/resolution.js | 6 +- extensions/steamworks.js | 245 - extensions/text.js | 96 +- extensions/true-fantom/math.js | 26 +- extensions/true-fantom/network-m.js | 16 +- extensions/true-fantom/network.js | 90 +- extensions/turboloader/audiostream.js | 96 +- extensions/utilities.js | 39 +- extensions/veggiecan/LongmanDictionary.js | 20 +- extensions/veggiecan/browserfullscreen.js | 62 +- extensions/vercte/dictionaries.js | 33 +- images/CST1229/images.svg | 141 - images/Clay/htmlEncode.svg | 1 - images/CubesterYT/KeySimulation.svg | 699 +- images/Eaielectronic/Finger-mutli-mobile.svg | 2 +- images/Eaielectronic/Login-page 2.svg | 1 - images/Eaielectronic/ScrollingTextBubble.svg | 1 - images/Lily/AllMenus.svg | 2 +- images/PwLDev/vibration.svg | 1 - images/README.md | 42 +- images/Skyhigh173/json.svg | 2 +- images/Xeltalliv/simple3D.png | Bin 55753 -> 0 bytes images/XeroName/Deltatime.svg | 9 +- images/XmerOriginals/closecontol.svg | 27 + images/XmerOriginals/closecontrol.svg | 1 - images/clipboard.svg | 70 +- images/fetch.svg | 141 +- images/obviousAlexC/SensingPlus.svg | 2 +- images/qxsck/data-analysis.svg | 2 +- images/shreder95ua/resolution.svg | 2 +- images/veggiecan/LongmanDictionary.png | Bin 0 -> 30683 bytes images/veggiecan/LongmanDictionary.svg | 1 - images/veggiecan/browserfullscreen.png | Bin 0 -> 59446 bytes images/veggiecan/browserfullscreen.svg | 1 - licenses/OFL-Lobster.txt | 93 - package-lock.json | 646 +- package.json | 16 +- samples/Pen Plus.sb3 | Bin 60455 -> 31212 bytes samples/Simple3D template.sb3 | Bin 22337 -> 0 bytes translations/extension-metadata.json | 853 +- translations/extension-runtime.json | 8614 ++--------------- website/Lobster.woff2 | Bin 101532 -> 0 bytes 126 files changed, 4968 insertions(+), 24732 deletions(-) delete mode 100644 docs/Xeltalliv/simple3D.md delete mode 100644 docs/steamworks.md delete mode 100644 extensions/Eaielectronic/Finger-mutli-mobile.js delete mode 100644 extensions/Eaielectronic/Fps-returne.js delete mode 100644 extensions/Eaielectronic/ScrollingTextBubble.js delete mode 100644 extensions/PwLDev/vibration.js delete mode 100644 extensions/Xeltalliv/simple3D.js delete mode 100644 extensions/steamworks.js delete mode 100644 images/CST1229/images.svg delete mode 100644 images/Clay/htmlEncode.svg delete mode 100644 images/Eaielectronic/Login-page 2.svg delete mode 100644 images/Eaielectronic/ScrollingTextBubble.svg delete mode 100644 images/PwLDev/vibration.svg delete mode 100644 images/Xeltalliv/simple3D.png create mode 100644 images/XmerOriginals/closecontol.svg delete mode 100644 images/XmerOriginals/closecontrol.svg create mode 100644 images/veggiecan/LongmanDictionary.png delete mode 100644 images/veggiecan/LongmanDictionary.svg create mode 100644 images/veggiecan/browserfullscreen.png delete mode 100644 images/veggiecan/browserfullscreen.svg delete mode 100644 licenses/OFL-Lobster.txt delete mode 100644 samples/Simple3D template.sb3 delete mode 100644 website/Lobster.woff2 diff --git a/development/builder.js b/development/builder.js index 0a91fab6b5..2b2bdf8a84 100644 --- a/development/builder.js +++ b/development/builder.js @@ -860,12 +860,12 @@ class Builder { chokidar .watch( [ - this.extensionsRoot, - this.imagesRoot, - this.websiteRoot, - this.docsRoot, - this.samplesRoot, - this.translationsRoot, + `${this.extensionsRoot}/**/*`, + `${this.imagesRoot}/**/*`, + `${this.websiteRoot}/**/*`, + `${this.docsRoot}/**/*`, + `${this.samplesRoot}/**/*`, + `${this.translationsRoot}/**/*`, ], { ignoreInitial: true, diff --git a/development/homepage-template.ejs b/development/homepage-template.ejs index e89fb72e2c..1491e491c5 100644 --- a/development/homepage-template.ejs +++ b/development/homepage-template.ejs @@ -258,19 +258,21 @@
TurboWarp Extension Gallery
-

This is the official extension gallery, where you can get extensions that aren't limited by the extension sandbox. All of the extensions here are reviewed for safety.

-

You can also find these extensions in TurboWarp's "Add Extension" menu.

+

Unlike custom extensions on other websites, these aren't limited by the extension sandbox, so they are a lot more powerful. All extensions are reviewed for safety.

+

+ To use multiple of these extensions in TurboWarp, hover over the extension and press the button to copy its URL. Then go to the editor, open the extension chooser, then choose the "Custom Extension" option at the bottom, and enter the URL. +

These extensions are not compatible with Scratch.
- Projects that use these extensions can't be opened in Scratch or uploaded to the Scratch website. - They can still be used in the TurboWarp packager. + Projects that use these extensions can't be uploaded to the Scratch website. + They can, however, be used in the packager.
Some extensions may not work in TurboWarp Desktop.
- To make sure extensions work offline, each release of TurboWarp Desktop comes with a copy of these extensions as of its release date, so some extensions may be outdated or missing. - Update to the latest version for the best results. + For compatibility, security, and offline support, each TurboWarp Desktop update contains an offline copy of these extensions from its release date, so some extensions may be outdated or missing. + Use the latest update for best results.
diff --git a/docs/Xeltalliv/simple3D.md b/docs/Xeltalliv/simple3D.md deleted file mode 100644 index 8fb8612456..0000000000 --- a/docs/Xeltalliv/simple3D.md +++ /dev/null @@ -1,1065 +0,0 @@ -# Simple 3D - -## Table of contents -1. [What is this](#description) -2. [How it works](#main-concepts) -3. [Drawing things](#simple-drawing) -4. [Setting up transformations](#transformations) -5. [Order in which different steps are performed](#step-order) -6. [Blocks](#blocks) -6.1. [Clearing](#blocks-clearing) -6.2. [Meshes](#blocks-meshes) -6.3. [Textures](#blocks-textures) -6.4. [Text measurement](#blocks-text-measurement) -6.5. [Fonts](#blocks-fonts) -6.6. [View transformations](#blocks-view-transformations) -6.7. [Manual transformations](#blocks-manual-transformations) -6.8. [Rendering into textures](#blocks-rendertargets) -6.9. [Tinting and fog](#blocks-tinting-fog) -6.10. [Resolution changes](#blocks-resolution) -7. [Integration with other extensions](#ext-integration) -7.1. [Augmented Reality extension](#ar-integration) - - -## What is this -**Simple 3D** is an extension by [Vadik1](https://scratch.mit.edu/users/Vadik1) meant to enable creation of GPU accelerated 3D projects. It is not designed for making graphically complex 3D projects (for that, see [Pen+ v7](https://github.com/TurboWarp/extensions/pull/1377) and [WebGL2](https://github.com/TurboWarp/extensions/discussions/378) extensions, both with programmable shaders) and instead it's main focus is allowing people to create 3D projects easily and quickly. Nevertheless, despite lack of programmable shaders, it is still quite powerful. It covers the wide range of usages from something as high level as making an [AR project in less than 20 blocks](#ar-example) with models loaded from OBJ files, to something more low level like doing all the calculations on CPU and streaming transformed polygons every frame (like [Pen+](https://extensions.turbowarp.org/obviousAlexC/penPlus.js)). And of course everything in-between. - -It could also be useful for making certain kinds of 2D projects, thanks to it's ability to render large quantities of similar objects with instancing (e.g. particles), construct 2D meshes out of triangles, rendering into textures allowing multi-pass rendering and more advanced clipping than [Clipping & Blending](https://extensions.turbowarp.org/Xeltalliv/clippingblending.js) extension. It can be used for 2D image processing that can for example later be used as costumes using [Skins](https://extensions.turbowarp.org/Lily/Skins.js) extension. It's support of vertex weights and indices can be used for skeletal animation of 2D characters with deforming body parts rather than using rigid images, or even for smoothly extending UI elements. - -## How it works -Scratch has a background layer, a video layer, a pen layer and a sprite layer. This extension adds another layer - simple3D between video and pen layers. **High quality pen mode also affects it.** - -The key concepts in this extension are the meshes and transformations. - -Meshes store the 3D model data and can be drawn. They are kind of like costumes in a stamp-based project. That is, if you want to make a project that draws many copies of some costume in different locations using stamps, you will only have 1 costume, store all the locations in a list in whatever format you consider appropriate, and every frame you will clear the screen and re-stamp that costume in all the locations from the list. - -It works the same way with this extension. If you have 10 identical 3D boxes, you will only create one mesh. Then every frame, first clear the screen, and after that loop over the list, for each box, setting up the correct transformation and drawing that one mesh. - -So in short, **this extension does not have any kind of scenes, objects, cameras, etc**, you have to keep track of it yourself. - ---- - -3D models consist of vertices which together form primitives (points, lines, triangles). Each vertex has either 2D (XY) or 3D (XYZ) location described with 2 or 3 numbers respectively. Before drawing the mesh, you would usually set up transformation, which tells how to take those initial locations and transform them to correct location on your 2D screen. The typical way to do it, is to chain multiple simple transformations together. Simple transformations can be translation (offsetting), rotation, scaling, mirroring, skewing, etc. - -## Drawing things -**Note:** For a more complete tutorial, see [here](https://xeltalliv.github.io/simple3d-extension/examples/) (external link). - -For now let's not worry about transformations and just draw something as is. -First step would be to clear the screen: -```scratch -set clear color R: (0.5) G: (0.5) B: (0.5) A: (1) :: sensing -clear (color and depth v) :: sensing -``` -After running that the screen should turn gray. -Now let's draw 2 triangles arranged into a rectangle. First create a mesh: -```scratch -create mesh [my mesh] :: sensing -``` -Then create 2 lists `posX` and `posY`. -Fill `posX` with: -``` --0.9 -0.9 --0.9 --0.9 -0.9 -0.9 -``` -Fill `posY` with: -``` --0.9 --0.9 -0.9 -0.9 --0.9 -0.9 -``` -then set mesh's positions to it: -```scratch -set [my mesh] positions XY [posX v] [posY v] :: sensing -``` -and finally draw it: -```scratch -draw [my mesh] :: sensing -``` -The result should look something like this: -![white rectangle on gray background](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAloAAAHEAgMAAACcsWzXAAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV/TSkUqImYQcchQnSyCiohTrUIRKoRaoVUH89EvaNKQpLg4Cq4FBz8Wqw4uzro6uAqC4AeIs4OToouU+L+k0CLGg+N+vLv3uHsHcI2KolmhOKDptplOJoRsblUIvyIEHv2YxbikWMacKKbgO77uEWDrXYxl+Z/7c/SqeUsBAgJxXDFMm3iDeHrTNhjvE/NKSVKJz4nHTLog8SPTZY/fGBdd5lgmb2bS88Q8sVDsYLmDlZKpEU8RR1VNp3wu67HKeIuxVqkprXuyF0by+soy02kOI4lFLEGEABk1lFGBjRitOikW0rSf8PEPuX6RXDK5ylDIsYAqNEiuH+wPfndrFSYnvKRIAuh6cZyPESC8CzTrjvN97DjNEyD4DFzpbX+1Acx8kl5va9EjoG8buLhua/IecLkDDD4Zkim5UpAmVygA72f0TTlg4BboWfN6a+3j9AHIUFepG+DgEBgtUva6z7u7O3v790yrvx8KVHLj7WPAsgAAAAlQTFRFNDQ0gICA////76SQuwAAAAlwSFlzAAAYTAAAGHQBn6hAIAAAAAd0SU1FB+gEFBIAAu2UQ3UAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAABNUlEQVR42u3OUQkAIBAFsCthH0toR01pAX+FB24JVhWqjUTdy8vLy8vLy8vLy8vr99fcEZaXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5fX7RXGy8vLy8vLy8vLy8vr/SvUAWUTfy76T1mWAAAAAElFTkSuQmCC) -The screen coordinate system used by this extension is not scratch's typical 480x360 (from -240 to 240 for X and from -180 to 180 for Y), but instead it is 2x2 (from -1 to 1 on both axis). It is the same as in WebGL and OpenGL. -Here we created triangles that have vertex coordinates at -0.9 and 0.9, which do not quite reach the boundaries of the screen, even though they get close. - -Also, here we specified 6 vertices. Each triangle has 3 vertices, so it was treated as 6/3=2 triangles. -But specifying 3 vertices per each triangle is not the only way. In cases when some vertices are the same for multiple triangles, there are ways to specify them once and reuse them afterwards rather than duplicating the data. There are 2 main ways to do it: - -### List of indices -With this way, there is a way to create another list which will reference which vertices to use in which order. To add it to our example: -Fill `posX` with: -``` --0.9 -0.9 --0.9 -0.9 -``` -Fill `posY` with: -``` --0.9 --0.9 -0.9 -0.9 -``` -Create another list `indices` and fill it with: -``` -1 -2 -3 -3 -2 -4 -``` -Now reupload XY positions and upload the list of indices into the mesh, clear the screen and draw the mesh again. Result should look the same. -```scratch -set clear color R: (0.5) G: (0.5) B: (0.5) A: (1) :: sensing -clear (color and depth v) :: sensing -create mesh [my mesh] :: sensing -set [my mesh] positions XY [posX v] [posY v] :: sensing -set [my mesh] vertex indices [indices v] :: sensing -draw [my mesh] :: sensing -``` - -### Chained primitive types -Another way to do it is to switch mesh from using just "triangles" to using "triangle strips" or "triangle fans". -With triangle strip, the first 2 vertices are processed normally, and then each subsequent vertex get combined with the previous 2 into a triangle. -With triangle fan, the first 2 vertices are processed normally, and then each subsequent vertex get combined with the previous one and the first one into a triangle. -```scratch -set clear color R: (0.5) G: (0.5) B: (0.5) A: (1) :: sensing -clear (color and depth v) :: sensing -create mesh [my mesh] :: sensing -set [my mesh] positions XY [posX v] [posY v] :: sensing -set [my mesh] primitives (traingle strip v) :: sensing -draw [my mesh] :: sensing -``` -Result should once again look the same. - -### Primitive restart index -"triangle strips" and "triangle fans" are no doubt efficient, but when using it you only get 1 long continious thing of triangles, meaning that to draw many "strips" or "fans" you will have to call "draw mesh" many times, cancelling the efficiency. -However there is a solution for it. You can use "triangle strips" and "triangle fans" together with list of indices. If you specify index 0 or below, it will interrupt the previous chain of triangles and restart a new one. - -Same applies to "line strip" and "line loop". - -## Setting up transformations -The typical sequence of simple transformation for 3D project goes like this: -First you start off with having a 3D model in it's own coordinate system (model space), with all vertex positions stored relatively from it's origin. The first step would be to transform it to the world coordinate system. If the object has it's own rotation, rotate every vertex around it's origin (0,0,0) by correct amount of degrees. If it is scaled, scale them. Then once that is done, offset every vertex by object's world position. Now positions of all of the vertices are in the world coordinate system (world space). - -The next step is to transfrorm them to the coordinate system relatively to the viewer, where viewer is at X:0, Y:0, Z:0 and is always facing negative Z. In 3D projects on normal scratch it is common for viewer to face positive Z, where the more Z something has, the further away it is in front of the viewer, but in case of this extension, it was designed like most software outside scratch - the **less** Z something has, the further it is in front of the viewer. To do this transformation, first subtract camera position from position of every vertex. That will place the camera in the origin of the world and make everything relatively to it, but rotation is still not taken into a count. To use it, rotate every point by negated/inverse camera rotation. - -What you now have are 3D positions relatively to the camera. But your screen is 2D, so the last step is to do the projection. The general gist of it is that you divide all X and Y by Z, so that the further something is, the smaller it is and the closer it is to the center of the screen. And while doing that, clipping everything that goes offscreen or too close and behind you. - -But in reality it's somewhat more complicated. -You first transform X, Y, Z into X, Y, Z and W of the clip space and then GPU automatically clips X, Y and Z to the rangle from -W to W, and then divides -X, Y, Z by W, so X, Y, Z end up in range from -1 to 1. Where W is the actual depth, while Z is depth converted to the correct range to be used with the -depth buffer (everything below -1 and above 1 gets clipped) (too far and too close). - -If that sounded complicated, do not worry, Simple3D extension mostly handles it for you. - -So let's recap: -``` -when given vertex coordinates x, y, z in model space: - -scale by object scale -rotate by object orientation -translate by object position - -translate by negative camera position -rotate by negative camera orientation - -convert to clip space - -divide X,Y,Z by depth W (done by GPU, cannot be controlled) -draw to the screen at X,Y. Use Z for depth check. -``` - -And now it's time to make some actual Simple3D scratch blocks code. -In Simple3D those transformations are combined into 1 big transformation, and all the steps have to be specified in reverse. -```scratch -start with perspective FOV (90) near (0.1) far (1000) :: sensing -rotate around [X v] by ((0) - (camRotX)) degrees :: sensing -rotate around [Y v] by ((0) - (camRotY)) degrees :: sensing -move X ((0) - (camX)) Y ((0) - (camY)) Z ((0) - (camZ)) :: sensing -move X (objectX) Y (objectY) Z (objectZ) :: sensing -rotate around [Y v] by (objectRotY) degrees :: sensing -rotate around [X v] by (objectRotX) degrees :: sensing -scale X (objectSizeX) Y (objectSizeY) Z (objectSizeZ) :: sensing -draw mesh [my mesh] :: sensing -``` - -Doing all of those steps again for every mesh you want to draw is inefficient. This is where doing steps in reverse becomes helpful. Combined with wrapper block, which saves the transformation when entering it, and restores it when exiting it, it is possible to do this: -```scratch -start with perspective FOV (90) near (0.1) far (1000) :: sensing -rotate around [X v] by ((0) - (camRotX)) degrees :: sensing -rotate around [Y v] by ((0) - (camRotY)) degrees :: sensing -move X ((0) - (camX)) Y ((0) - (camY)) Z ((0) - (camZ)) :: sensing -repeat (10) -wrapper { -... -move X (objectX) Y (objectY) Z (objectZ) :: sensing -rotate around [Y v] by (objectRotY) degrees :: sensing -rotate around [X v] by (objectRotX) degrees :: sensing -scale X (objectSizeX) Y (objectSizeY) Z (objectSizeZ) :: sensing -draw mesh [my mesh] :: sensing -} :: sensing -end -``` -This will work and it is efficient, however this extension also provides advanced features like fog, instancing, billboarding, which need to intervine in some of the intermediate steps. -And when you create one large transformation by youself, it has no way of doing that. Which is why, currently the correct way to setup transformations is like this: -```scratch -configure [to projected from view space v] transformation :: sensing -start with perspective FOV (90) near (0.1) far (1000) :: sensing - -configure [to view space from world space v] transformation :: sensing -start with no transformation :: sensing -rotate around [X v] by ((0) - (camRotX)) degrees :: sensing -rotate around [Y v] by ((0) - (camRotY)) degrees :: sensing -move X ((0) - (camX)) Y ((0) - (camY)) Z ((0) - (camZ)) :: sensing -repeat (10) -... -configure [to world space from model space v] transformation :: sensing -start with no transformation :: sensing -move X (objectX) Y (objectY) Z (objectZ) :: sensing -rotate around [Y v] by (objectRotY) degrees :: sensing -rotate around [X v] by (objectRotX) degrees :: sensing -scale X (objectSizeX) Y (objectSizeY) Z (objectSizeZ) :: sensing -draw mesh [my mesh] :: sensing -end -``` -The extension allows you to split your large transformation into 3 separate transformations, which will be applied sequentially, allowing some of the features to do their thing inbetween. -It also allows you to easily got between different coordinate systems using those blocks: -```scratch -transform X (0) Y (0) Z (0) from [world space v] to [model space v] :: sensing -transform direction X (0) Y (0) Z (0) from [world space v] to [model space v] :: sensing -``` - -## Order in which different steps are performed -### Vertex positions -For each vertex, the final position calculation goes as follows: -1. vertex position is read -2. skinning is applied -3. transformed from model space to world space -4. transformed by instance transform -5. transformed from world space to view space -6. transformed from veiw space to clip space -7. division of XYZ by W (performed automatically by the GPU) - -When billboarding is enabled: -1. vertex position is read -2. skinning is applied -3. transformed from model space to world space -4. position is copied elsewhere, while original is replaced by (0,0,0) -5. transformed by instance transform -6. transformed from world space to view space -7. saved position is added to current position -8. transformed from veiw space to clip space -9. division of XYZ by W (performed automatically by the GPU) - -### Vertex colors -1. vertex color is read, white if not provided -2. multipled by instance color - -### Vertex UVs -For each vertex, the UV texture coordinates at it are calculated as follows: -1. vertex UVs are read -2. scaled by instance UV scale (3rd and 4th components) -3. added instance UV offset (1st and 2nd components) -4. mesh UV offset is applied - -### Pixel Colors -For each pixel, the final color calculation goes as follows: -1. texture is read or white if texture is not provided -2. multipled by interpolated vertex color RGBA -3. alpha threshold check is performed -4. make opaque is applied -5. multipled by global color multipler -6. added global color adder -7. fog is aplied - - -## Blocks -### Clearing -```scratch -reset everything :: sensing -``` -Resets everything to the initial state as if the extension was freshly loaded. It also deletes meshes and shader cache. - ---- -```scratch -clear (color and depth v) :: sensing -``` -Clears the color and/or depth of the selected render target. - ---- -```scratch -set clear color R:(0.5) G:(0.5) B:(0.5) A:(1) :: sensing -``` -Sets clear color to the specified Red, Green, Blue and Alpha (Opacity) values in range from 0 to 1. -Clear color is a global value. - ---- - -```scratch -set depth test (closer v) write (on v) :: sensing -``` -Before new pixel is drawn, it's depth is compared to the pixel already drawn on that location. -If it passes according to the check in the first argument of this block, it gets drawn. If it fails, the new pixel gets discarded, and whatever was there remains there. -The second argument controls when check passes whether only color should be updated or both color and depth value. Turning this off can be useful for drawing transparent things, which should react to already drawn opaque things, while not modifying depth to not interfer with each other. -**Depth test and write are values that are saved separately for each render target.** -Despite all 6 sides of the cube texture being different render targets, they still share those values. - -For stage, default values are "closer" and "on". **However, for textures used as render targets default values are "everything" and "off".** Memory for storing depth is not even allocated until depth write is set to "on". - - -### Meshes -```scratch -(all meshes :: sensing) -``` -Lists all the mesh names separated by commas. Mainly meant to be used manually for debugging purposes. - ---- -```scratch -create mesh [my mesh] :: sensing -``` -Creates an empty mesh with the specified name. If mesh with such name already exists, the old one gets fully deleted first. - -Also, whitespaces at both ends of the name, as well as any commas get removed from the mesh name. This is done for compatibility with "make mesh inhert" block. - ---- -```scratch -delete mesh [my mesh] :: sensing -``` -Deletes mesh with the specified name. - ---- -```scratch -make mesh [my mesh 3] inherit from meshes [my mesh 1,my mesh 2] :: sensing -``` -Sets up the first mesh to inherit any lists or properties from multiple other meshes. -If multiple other meshes have the same property, the last one takes the priority. -If any of the specified meshes to inherit form a cyclic dependancy, the entire operation fails. -Names are provided in a comma separated list. Mesh names are trimmed from spaces on both ends. So `my mesh 1,my mesh 2`, `my mesh 1, my mesh 2`, and ` my mesh 1 , my mesh 2 ` will all behave the same. - -This is the a key feature meant to avoid data duplication. When using it, nothing that could be expensive is duplicated. -**Use this instead of uploading the same lists or textures into multiple different meshes.** -You can even rapidly change what meshes are inherited while the project is running. - ---- -```scratch -(mesh [my mesh] [inherits from v] :: sensing) -``` -Used to obtain properties of a mesh. - ---- -```scratch -set [my mesh] vertex indices [list v] :: sensing -``` -An optional mesh list used to provide the order in which vertices are read and used to construct primitives. -Starts from 1. Specifying value 0 or below can be used to break up "triangle strip", "traingle fan", "line strip" and "line loop" into multiple ones. - ---- -```scratch -set [my mesh] positions XY [listX v] [listY v] :: sensing -set [my mesh] positions XYZ [listX v] [listY v] [listZ v] :: sensing -``` -Used to upload vertex positions into the mesh. -**The only mandatory list for mesh to become drawable.** - ---- -```scratch -set [my mesh] colors RGB [listR v] [listG v] [listB v] :: sensing -set [my mesh] colors RGBA [listR v] [listG v] [listB v] [listA v] :: sensing -``` -Used to upload vertex colors (as red, green, blue and alpha) into the mesh. -Values mush be integers in range between 0 and 255. - ---- -```scratch -set [my mesh] texture coordinates UV [listU v] [listV v] :: sensing -set [my mesh] texture coordinates UVW [listU v] [listV v] [listW v] :: sensing -``` -Used to upload texture coordinates into the mesh. -The 2 component one is used for 2D textures. Specifies 2D coordinates on a texture, which go from 0 to 1. But values outside of those bounds are also valid and useful. -The 3 component one is used for cube textures (cubemaps). Specifies 3D direction from the center, which will be intersected with the cube around it. -If texture coordinates are specified, but texture is not, the default texture is used. - ---- -```scratch -set [my mesh] texture () [clamp to edge v] [pixelated v] :: sensing -set [my mesh] cube texture (X+ v) () [clamp to edge v] [pixelated v] :: sensing -``` -Used to upload texture into the mesh. -Calling this block depending on the type of texture used either uploads texture instantly (e.g. empty or text) or schedules texture to be uploaded into the mesh some time in the future (e.g. load from url or from costume). -**So if for example you upload texture from a costume and immediately try to draw this mesh once, you will not see it. It takes time to load!** - -Use the block below to check if the texture has finished loading. -```scratch -(mesh [my mesh] [texture is loading v] :: sensing) -``` - -The 2nd(3rd) argument controls what happens when UV coordinates are out of 0..1 range: - - `clamp to edge` - will find the closest point within allowed range and use color of that. This basically infinitely stretches edges of the texture. - - `repeat` - the texture is repeated out of bounds. UV 1.5 0.6 is the same as 13.5 -0.4 - -The 3rd(4th) argument controls how each pixel obtains the color from the texture: - - `pixelated` - rounds down UV to the coordinates the closest pixel and gets it's color - - `blurred` - takes a weighted average between 4 pixels UV falls inbetween - -The 1st argument in cube texture controls to which of 6 sides the texture should be uploaded. It must be square and the same size as all other sides. -Uploading non-matching size will cause all other sides to clear themselves. -Uploading non-square size texture will fail and do nothing. - -The type of texture that the mesh will have can only be set once. If the mesh has cube texture, trying to replace it with the 2D texture will fail. If the mesh has 2D texture, trying to replace it with the cube texture will also fail. - ---- -```scratch -set [my mesh] texture mipmapping [off v] :: sensing -``` -Used for enabling and disabling mipmapping. -When enabling, regenerates mipmaps. -When mipmapping is enabled, uploading textures regenerates mipmaps as well. - -Mipmapping is a technique of having texture in multiple different resolutions (mipmaps) and whenever something is either far away or viewed at a steep angle, switching to using lower resolution version of the textures. -It help eliminate pixel shimmering and with high resolutions, can also improve performance (low resolution versions of textures can fit in GPU cache, allowing far away geometry to be drawn very quickly). - -Default for mesh is "off". - ---- -```scratch -set [my mesh] texture anisotropic filtering (16 v) :: sensing -``` -Used for setting anisotropic filtering. -1 is no anisotropic filtering. -16 is maximum. -**It is not supported on all GPUs! Maximum value also varies depending on GPU.** -Always setting it to 16, regardless of whether it is supported or what values are supported is still totally fine. Performance on underpowered devices that support it will no be fine though. So adding a toggle is a good idea. - -Default for mesh 1. - ---- -```scratch -set [my mesh] bone indices [listIndices v] weights [listWeights v] count per vertex (3) :: sensing -``` -Used for setting bone indices and weights. -Count per vertex must be in range between 1 and 4. -Indices start from 1. -Weights are not used when count per vertex is 1. -Length of supplied indices and weights lists have to match and be divisible by "count per vertex". - ---- -```scratch -set [my mesh] [original v] transforms [listTransforms v] :: sensing -set [my mesh] [current v] transforms [listTransforms v] :: sensing -``` -Used for setting original and current transforms of each bone. -Transforms on how to get from original to current will be calculated and applied to vertices based on their bone indices and weights. -Supplied list of transforms must have length divisible by 16. If not, operation fails. -Setting original transforms is optional. Missing original transforms are treated as empty transforms. - ---- -```scratch -set [my mesh] interleaved [XY positions v] [list v] :: sensing -``` - -Used for setting vertex data. Does the same as those blocks: -```scratch -set [my mesh] positions XY [listX v] [listY v] :: sensing -set [my mesh] positions XYZ [listX v] [listY v] [listZ v] :: sensing -set [my mesh] colors RGB [listR v] [listG v] [listB v] :: sensing -set [my mesh] colors RGBA [listR v] [listG v] [listB v] [listA v] :: sensing -set [my mesh] texture coordinates UV [listU v] [listV v] :: sensing -set [my mesh] texture coordinates UVW [listU v] [listV v] [listW v] :: sensing -``` -but from a single list with all the components interleaved. - ---- -```scratch -set [my mesh] instance [transfroms v] [list v] :: sensing -``` -Used for setting data for instancing: drawing the same mesh many times (can be over a million) in multiple locations. - -Only one in each of the following 3 catergories is allowed. Setting another one replaces the old one. - -Positioning: - - `transforms` - a list of transforms, with total length divisible by 16. - - `XY positions` - a list of interleaved X and Y positions, with total length divisible by 2. - - `XYZ positions` - a list of interleaved X, Y and Z positions, with total length divisible by 3. - - `XYZ positions and sizes` - a list of interleaved X, Y, Z positions and sizes, with total length divisible by 4. - -Colors: - - `RGB colors` - a list of interleaved red, green and blue color components, with total length divisible by 3. - - `RGBA colors` - a list of interleaved red, green, blue and alpha color components, with total length divisible by 4. - -Texture coordinates: - - `UV offsets` - a list of interleaved U and V texture coordinate offsets, with total length divisible by 2. - - `UV offsets and sizes` - a list of interleaved U, V texture coordinate offsets and U, V texture coordinate scaling factors, with total length divisible by 4. - -Setting positioning is required for instancing to activate. - -All defined catergories have to have data for the same amount of instances. If the amount of instances inferred from the length of those lists do not match, mesh is not valid for drawing and cannot be drawn. - ---- -```scratch -set [my mesh] list update offset (1) :: sensing -``` -Allows partially updating mesh data instead of fully reuploading. - -Starts from 1. -Having it set to 1 or above enables partial update mode. -Having it set to 0 or below disables partial update mode and makes lists update fully. -In partial update mode you can only update existing data. If your new data is too long and goes out of bounds of what is already set for the mesh, the operation will fail. -**If you accidentally enabled it and want to disable it, set it to 0, not 1!** -That is because while both update list from the start, when you have it at 1, partial update mode is enabled and you cannot resize the data. If you try to upload more it will fail. If you try to upload less, the end will remain unchanged. - -**This is one of 2 properties that is not inherited.** This is done for performance reasons and to reduce chances of misuse. - -**If you need to update data fully, do not use partial update mode at offset 1 to "save memory". It only makes things worse.** Only use it when you need to update only relatively a small section of data. - -Default for mesh is 0. - ---- -```scratch -set [my mesh] optimize next uploaded lists for being [rarely v] updated :: sensing -``` -Used for hinting GPU driver on how the data should be prepared. Different GPU drivers will handle it differently. - -Usually you create mesh, set static data once, then toggle this to one of the frequent modes and start updating some that frequent data. -If you suddenly need to update static data again, do not forget to temporarily switch it to "rarely", before setting that data. - -This only affects vertex related data. It does not affect uploading texture pixel data from a list. - -**This is one of 2 properties that is not inherited.** This is done for performance reasons and to reduce chances of misuse. - -Deafult for mesh is "rarely". - ---- -```scratch -set [my mesh] from [obj mtl v] [list v] :: sensing -set [my mesh] from [off v] [list v] :: sensing -``` -Decodes a 3D model file and uploads it into a mesh. Block continues instantly, but the model loading is performed in a separate thread, and it finishes with a delay. Currently, only one thread is used, so everything is queued and processed one by one. In the future, multiple threads might be used. - -**Note: This block is designed as a more of a shortcut for quick testing, rather than the main way of loading 3D models. For anything more complex make your own 3D model parser.** - -File formats: - - [obj](https://en.wikipedia.org/wiki/Wavefront_.obj_file) is a very common and well known 3D model file format. It supports UV texture coordinates, materials with colors and textures. However it does not have a standartized way to do vertex colors. This block implements a non-standart but widely supported way to represent vertex colors as 4th - 7th elements of `v`. The OBJ and MTL specification describes a lot of features, only some of which are currently (or even can be) supported by this importer. In particular, there is currently no way to import models which use multiple textures as this extensions only supports 1 texture per mesh. Normals and anything lighting related isn't and can't be supported. **In case both OBJ and MTL files need to be imported, combine them all into 1 list sequentially, first all of the MTL files and then the OBJ file.** - - [off](https://en.wikipedia.org/wiki/OFF_(file_format)) is a not that well known, but very simple file format. Is is quite neat for the use in scratch in general, as it's simpler than OBJ and unlike it, natively supports both vertex and face colors. It does not support textures or texture coordinates. You can read more about it and find a lot of example models [here](http://web.archive.org/web/20230331211230/https://people.sc.fsu.edu/~jburkardt/data/off/off.html). - -Imported model is affected by transformation set with: -```scratch -configure [importing from file v] transformation :: sensing -``` - ---- -```scratch -set [my mesh] primitives (points v) :: sensing -``` -Used for changing the way vertices are assembled into primitives. -- With triangles, vertices are grouped by 3 into triangles. -- With triangle strip, the first 2 vertices are processed without anything, and then each subsequent vertex get combined with the previous 2 into a triangle. -- With triangle fan, the first 2 vertices are processed without anything, and then each subsequent vertex get combined with the previous one and the first one into a triangle. -- With lines, vertices are grounded by 2 into lines. -- With line strip, the first vertiex is processed without anything, and then each subsequent vertex get combined with the previous one into a line. -- With line loop, the first vertiex is processed without anything, and then each subsequent vertex get combined with the previous one into a line and the last one gets also linked back to the first one. -- With points, each vertex turns into a point. - -When using vertex indices, specifying vertex index 0 or below can be used to break up "triangle strip", "triangle fan", "line strip" and "line loop" into multiple ones. - -Default for mesh is "triangles". - ---- -```scratch -set [my mesh] blending (default v) :: sensing -``` - -Used for setting how mesh will be blender with what is already drawn. - -If your mesh is fully opaque, use "overwrite color (fastest for opaque)". If your mesh is transpartent instead, you can use it to draw transparent holes in an already opaque image. -Use invisible for drawing to the depth buffer. -Everything else is self-explanatory and the same as in [Clipping & Blending](https://extensions.turbowarp.org/Xeltalliv/clippingblending.js) extension. - -Default for mesh is "default". - ---- -```scratch -set [my mesh] cull (back faces v) :: sensing -``` -Used for enabling/disabling backface/frontface culling. Basically making triangle visible only from one side, depening of whether their vertices appear on the screen in the clockwise or counter-clockwise order. - -Deafult for mesh is "nothing". - ---- -```scratch -set [my mesh] discard pixels less opaque than (0.5), and for those that pass [make opaque v] :: sensing -``` - -Used for disacrding pixels that are below specific opacity threshold and optionally making everything opaque. - -Useful for drawing text or textures of leaves, where the texture itself should be either fully opaque or fully transparent, with texture alpha being used for determining where the sharp cutoff edges should be. - -Default for mesh is threshold:0 preserve opacity. - ---- -```scratch -set [my mesh] billboarding (on v) :: sensing -``` -Used for enabling and disabling billboarding. -When billboarding is enabled, the mesh is always facing in the opposite direction to your look direction (behind you). -Note that it is not the same as turning towards your position. - -Default for mesh is "off". - ---- -```scratch -set [my mesh] accurate interpolation (on v) :: sensing -``` -(DEPRECTATED) -Used for enabling a more accurate interpolation method which doesn't have issues of texture coordinates extrapolating outside of the specified range on the triangle edges, causing unpleasant looking seams. It is more computationally expensive and should only be used when that is an issue. -Enabling mipmapping and/or anisatropic filtering may prevent it from working and reintroduce seams. - -Default for mesh is "off". - ---- -```scratch -set [my mesh] compute color (once at pixel center v) :: sensing -``` -Replaces the deprectated "accurate interpolation" block. - -Changes how color of each pixel is computed when MSAA antialiasing is enabled. - -Sometimes it can be beneficial for visulas to make edges of rendered 3D graphics smoothed out instead of having sharply transitioning pixel colors. That is the problem that different antialiasing techniques are trying to slove. For now, in Simple3D extension MSAA antialiasing is always enabled for the main Simple3D layer, and always disabled when rendering to textures. - -The simplest way to do antialiasing is called [Supersampling](https://en.wikipedia.org/wiki/Supersampling) and consists of rendering the image at higher resoultion then what is needed and then downscaling it to lower resolution by averageing colors. It works, but it is quite slow. - -A cheaper alternative to supersampling is a technique known as [Multi-sample Antialiasing (MSAA)](https://en.wikipedia.org/wiki/Multisample_anti-aliasing). It still consists of rendering the image at higher resolution by giving each pixel multiple sub-pixels, however, the color for all the sub-pixels of a pixel is only computed once, usually based on position in the center of the pixel. At the end, the colors of all of the sub-pixels get averaged and the result is a rendered image with smooth edges. Sub-pixels are often referred as samples. - -Unlike supersampling, MSAA only smoothes out primitive edges and not the sharp pixelated transitions on the primitive itself (e.g. textures). - -- `once at pixel center` - - This is a typical MSAA as described above. - - It has an issue where if some of the samples on the edge of a pixel fall within the drawn primitive, but the center of a pixel doesn't, then the color will still be computed for the center of the pixel, causing passed in UV coordinates and vertex colors to be extrapolated beyond the specified range. It often results in visible texture seams casued by adjacent texture data bleeding into pixels that shouldn't have it or incorrect colors on edges. - - Though, for most use cases this option is good enough with issue not being noticable. Since this is computationally the cheapest option, it is default. -- `once at midpoint of covered samples` - - This solves the issue described above by still computing color once, but instead of always doing it in the center of the pixel, which may not always fall within the primitive, it does it at the midpoint of all the samples that passed the inside-of-primitive check. Since all primitives are convex, this midpoint is also guaranteed to be within the primitive. This option is more computationally expensive, and as such, disabled by default. - -- `separately for each sample` - - Computes color separately at each sample, turning this into Supersampling. This option relies on OES_shader_multisample_interpolation and as such isn't supported everywhere. It is also the most computationally expensive option. - -Note that enabling mipmapping and/or anisatropic filtering may reintroduce seams regardless of what was selected with this block. - -Using `separately for each sample` with fallback to `once at midpoint of covered samples` can be implemented by calling the block twice. Selecting `separately for each sample` when it isn't supported will do nothing and keep the previous value. - -Default for mesh is "once at pixel center". - ---- -```scratch -set [my mesh] vertex draw range from (1) to (6) :: sensing -``` -Used for drawing mesh partially by only drawing some range of the vertices. - -Could be useful in cases where the mesh keeps changing (including amount of vertices and primitives). -For cases like that, prepare a lot of dummy vertex data in advance. Then only fill and start drawing the beginning of it. -Use partial updates to add any extra polygons after the range that is being drawn and then extend the range to include them. -To remove polygons, move the ones from the end of the drawing range to location of the remove one and then shring the drawing -range at the end. - -Default for mesh is not set. Once set, cannot be undone. - ---- -```scratch -set [my mesh] instance draw limit (10) :: sensing -``` -Normally, how many instances are drawn is determined by the length of supplied lists. -This block can be used to limit the amount of instances drawn to an even lower number. -This can be useful together with partial list updates to be able to dynamically change amount of drawn instances without having to reupload the entire list. That is, preallocating space for some amount of instances in advance, but drawing less. When new instance needs to be added, using partial updates to update the instance data of the next unused instance and then increasing the limit by 1. To remove an instance, the last instance can be moved in it's place and then the limit reduced by 1. - -Setting to any value below 1 is equivalent to setting it to Infinity. - -Default for mesh is Infinity. - ---- -```scratch -set [my mesh] texture coordinate offset UV (0) (0) :: sensing -``` -Used for offsetting texture UVs. -Combined with textures with "repeat" mode and timer block, this can be used to very easily create meshes with scrolling textures. - -Default for mesh is 0,0. - ---- -```scratch -draw mesh [my mesh] :: sensing -``` -Draws the specified mesh one or multiple (instancing) times, but only if it is valid. - -Mesh is invalid and cannot be drawn if: - - vertex positions are not set - - lists that were uploaded to it imply mismatching amounts of vertices or instances - -This block may cause stutter when drawing something for the first time, as it will need to generate and compile shaders. - - -### Textures -```scratch -(texture from URL [https://extensions.turbowarp.org/dango.png] :: sensing) -``` -Creates texture from image at specified URL. -Will show a prompt if URL is not approved. -If an image fails to load, you can usually open browser console and see what the error is. (F12 or Ctrl+Shift+I) -**Note that websites cannot access any data from any other websites unless those other sites explicetly allow it. The correct term for it is CORS (Cross Origin Resource Sharing). You can use some CORS proxy to bypass it.** -🐢 Texture gets loaded with a delay. - ---- -```scratch -(texture from costume [costume1 v] :: sensing) -``` -Creates texture from costume. -🐢 **Texture gets loaded with a delay. When doing image processing, do not attempt to load and instantly draw. It would not show up!** - -**Do not forget: bitmap costumes have 2x2 subpixels, which here are counted as pixels.** So do not be surprized when your seemingly 8x8 costume turns into 16x16 texture. - -**When using TurboWarp Packager, you need to disable "Remove raw asset data after loading to save RAM" in order for this block to work.** - ---- -```scratch -(texture from text [Hello World!] font [italic bold 32px sans-serif] color (#ffff00) :: sensing) -(texture from text [Hello World!] font [italic bold 32px sans-serif] color (#ffff00) border (5) (#000000) :: sensing) -``` -Creates texture with specified text. -⚡ Texture gets loaded instantly. -Border extends texture by it's value of pixels in all 4 directions. -For more information on the font argument syntax, see [CSS Specification](https://drafts.csswg.org/css-fonts/#font-prop). - ---- -```scratch -(texture from list [list v] at (1) of size (16) (16) :: sensing) -``` -Creates texture from RGBA data in a list. Each pixel is represented with list 4 elements, each in range between 0 and 255. Elements are: red, green, blue, alpha. -Note that it is not alpha, red, green, blue used by many pen projects on scratch. -⚡ Texture gets loaded instantly. - ---- -```scratch -(texture of size (16) (16) :: sensing) -``` -Creates black texture of given size. -⚡ Texture gets loaded instantly. - - -### Text measurement -```scratch -measure text [Hello World!] font [italic bold 32px sans-serif] :: sensing -(measured (up v) size ::sensing) -``` -Used for measuring how the text texture was or will be generated. -Outputs 4 sizes. Sizes can be negative. - - -### Fonts -```scratch -(font [Sans Serif] of size [32] :: sensing) -``` -Used for getting internal names of default and custom fonts. It is not neccesary to use. - - -### View transformations -```scratch -configure [to projected from view space v] transformation :: sensing -``` -Used for switching between which of the few transformations is currently active for editing. -Transformations `to world space from model space`, `to view space from world space`, `to projected from view space` are 3 sequential transformation used for drawing, explained at the top of this page. -Transformation `importing from file` affects how the block below works: -```scratch -set [my mesh] from [.obj .mtl v] [list v] :: sensing -``` -Transformation `custom` does not affect anything. Use it for your own calculations. - ---- -```scratch -start with perspective FOV (90) near (0.1) far (1000) :: sensing -``` -Overwrites currently active transformation with the viewspace to clipspace conversion transformation for perspective projection. -**Camera is assumed to be facing negative Z.** -FOV is verical field of view and it is measured in degrees. -Anything closer than "near" or further than "far" will be clipped. - -Something to keep in mind is that depth buffer has limited precision. -The whole range between "near" and "far" get mapped to the whole range of depth buffer. -So, setting near and far to be close to one another makes depth more precise. -Setting near and far to vastly different value will cause Z-fighting issues caused by lack of precision. - -**Another thing to keep in mind is that this block requires aspect ratio.** To not bother it's users, it was decided to make it take aspect ratio of the currently active rendering target. Most projects do not change aspect ratio while running, but if you plan to support that, recalculate this every time after getting: -```scratch -when resolution changes :: sensing hat -``` - ---- -```scratch -start with orthographic near (0.1) far (1000) :: sensing -``` -Overwrites currently active transformation with the viewspace to clipspace conversion transformation for orthographic projection. -**Camera is assumed to be facing negative Z.** -Same regarding "near", "far", and aspect ratios as the block described above. - ---- -```scratch -start with no transformation :: sensing -``` -Overwrites currently active transformation with transformation that does nothing and keeps everything as is. - ---- -```scratch -start with [external source v] :: sensing -``` -Overwrites currently active transformation with transformation obtained from the external source. Hidden by default. External sources can be provided by other extensions. - ---- -```scratch -start with saved in [list v] at (1) :: sensing -``` -Overwrites currently active transformation with transformation from the list. Reads 16 values starting from the index specified by the second argument. - ---- -```scratch -move X (0) Y (0) Z (0) :: sensing -rotate around [X v] by (0) degrees :: sensing -scale X (1) Y (1) Z (1) :: sensing -``` -Applies change to currently selected transformation - ---- -```scratch -wrapper { -} :: sensing -``` -Saves all 5 transformations (not just currently selected) when entering, restores when exiting. For technical reasons does not currently restore, if the script inside called: -```scratch -stop [this script v] -``` - -**Also has 1 frame delay to exit, because it is technically treated as a loop. And similarly to loops, you can use `run without screen refresh` custom blocks to remove the delay.** - ---- -```scratch -save into [list v] at (1) :: sensing -``` -Overwites 16 elements in list starting from the specified item, with the numbers representing currently selected transformation. - ---- -```scratch -reset transformation's (offset v) :: sensing -``` -Resets offset or rotation of the transformation. - -Rotation without offset can be useful for transforming directions or drawing skyboxes. -Offset without rotation can be useful for positioning something at the end of the long chain of transformations, but rotating it independently afterwards relatively to the world. - - -### Manual transformations -```scratch -transform X (0) Y (0) Z (0) :: sensing -``` -Transforms point using currently selected transformation. It is the fastest way to transform coordinates, especially if there are a lot of them. - ---- -```scratch -transform X (0) Y (0) Z (0) from [world space v] to [model space v] :: sensing -transform direction X (0) Y (0) Z (0) from [world space v] to [model space v] :: sensing -``` -Transforms point from specified coordinate system to another. Convenient, but slower. -Transform direction only applies rotations and does not apply offsets. - -"projected" is pre-division clip-space coordinates. -"projected (scratch units)" does division by W and scaling to current stage size (e.g. 480x360). It can be used to determine where some point will end up on the screen with the current transformation to position sprite over it or draw something with pen. - - -### Rendering into textures -```scratch -render to stage :: sensing -``` -Selects simple3D layer as an active render target. - ---- -```scratch -render to texture of [my mesh] :: sensing -``` -Selects 2D texture of specified mesh as an active render target. -Fails if there is no texture or texture is not 2D. - ---- - -```scratch -render to cube texture (X+ v) of [my mesh] :: sensing -``` -Selects side of cube texture of specified mesh as an active render target. -Fails if there is no texture, texture is not cube or side is not valid. - ---- -```scratch -read current render target into [list v] :: sensing -``` -Reads the pixel data of the current render target into the list. -There are 4 values per pixels: red, greeen, blue, alpha. -Values should be in range between 0 and 255. - -Internally extension stores everything with premultiplied alpha. When reading this, it divides by alpha to restore directly respreseted colors. - ---- -```scratch -(render target [width v] :: sensing) -``` -Allows reading properties of the current render target. - ---- -```scratch -set [viewport box v] to X1:(0) Y1:(0) X2:(100) Y2:(100) :: sensing -set [clipping box v] to X1:(0) Y1:(0) X2:(100) Y2:(100) :: sensing -set [readback box v] to X1:(0) Y1:(0) X2:(100) Y2:(100) :: sensing -``` -Configures custom rectangular areas for different purposes for the currently active render target. -Viewport box specifies the area to which the rendered image will be stretched to cover from it's normal -1 to 1 range. -Clipping box specifies the area in which pixels are allowed to be modified. -Readback box specifies the area from which reading to list and reading to data URI blocks will read the pixels. - -Note: coordinates are specified in **real pixels** starting from the bottom left corner, **not scratch units**. You can get the size of the Simple3D layer in pixels from either: -```scratch -(stage width :: sensing) -(stage height :: sensing) - -(render target [width v] :: sensing) -(render target [height v] :: sensing) -``` -And while it may match scratch units while the high quality pen is disabled, when **high quality pen is on**, the resolution will often be higher. Your projects need to account for that. - -Note: Those custom areas can either be set or not set. When they aren't set, they use X1:`0` Y1:`0` X2:`render target width` Y2:`render target height` and automatically update with resolution changes. If you set them to custom values, you need to handle rescaling manually. - ---- -```scratch -clear [viewport box v] :: sensing -clear [clipping box v] :: sensing -clear [readback box v] :: sensing -``` -Removes the custom rectangular areas configured by the block described above. - - -### Tinting and fog -```scratch -set global color [multiplier v] to R: (1) G:(1) B:(1) A:(1) :: sensing -set global color [adder v] to R: (0) G:(0) B:(0) A:(0) :: sensing -``` -Allows setting up linear transformation to color. -Input color RGBA is multiplied by "multiplier" and then the "adder" values are added. -Here 0 is fully dark and 1 is full brightness. Values above 1 or below 0 will get clamped. -This is a global value. It is okay to change it many times per frame. - -Deafult multiplier is R:1 G:1 B:1 A:1. -Deafult adder is R:0 G:0 B:0 A:0. - ---- -```scratch -turn fog (on v) :: sensing -``` -Used for toggling fog on or off. Accepts a boolean argument (true or false). -This is a global value. It is okay to change it many times per frame. -Default is off. - ---- -```scratch -set fog color R:(1) G:(1) B:(1) :: sensing -``` -Sets fog color. -Default is R:1 G:1 B:1. - ---- -```scratch -set fog distance near: (10) far: (100) :: sensing -``` - -Sets fog distance. -`Near` sets the distance at which mesh starts transition into the fog color. -`Far` sets the distance at which mesh fully finishes transitioning into the fog color. - -Setting `near` to value greater than `far` results is a fog that starts close, and fades off with a distance. -Setting both arguments to the same value results in division by 0 and leads to undefined results, so avoid doing it. - -Default is near:10 far:100. - ---- -```scratch -set fog [view space v] origin at X: (0) Y: (0) Z: (0) :: sensing -``` -Specifies the center point around which the fog will be drawn. -Default is X:0 Y:0 Z:0 in view space. - -### Resolution changes -```scratch -when resultion changes :: sensing hat -(stage width :: sensing) -(stage height :: sensing) -``` -simple3D layer automatically always matches the resolution of the pen layer (or what resolution pen layer would have if it was present, even when pen layer is missing). -That means that by default, at default stage size it is locked to 480x360, but with "High quality pen" enabled or non-default stage sizes, it can become something different. -Hat block gets triggered when that resoltion changes. -Reporter blocks report current resolution. - -Technically those blocks could be workarounded by contantly checking with blocks listed below. -```scratch -render to stage :: sensing -(render target [width v] :: sensing) -(render target [height v] :: sensing) -``` - -## Integrations with other extensions - -Simple 3D can have integrations with other extensions. If you are an extension developer, see `Scratch.vm.runtime.ext_xeltallivSimple3Dapi` for that. - -### Augmented Reality extension - -While it is possible to upload all 16 components from matrices provided by Augmented Reality extension into transforms of this extension, - -```scratch -configure [to projected from view space v] transformation :: sensing -set [i v] to (0) -repeat (16) -change [i v] by (1) -replace item (i) of [list v] with (item (i) of [projection v] matrix :: #d10000) -end -start with saved in [list v] at (0) :: sensing -``` -to make this process easier, an extra feature was added. - -When Simple 3D extension and Augmented Reality extension are present in the project at the same time, users get access to the following extra blocks: -```scratch -start with (AR: combined v) :: sensing -start with (AR: view to projected v) :: sensing -start with (AR: view to world v) :: sensing -start with (AR: world to view v) :: sensing -``` -Those blocks copy values from AR extension identically to the repeat loop example above, but do it in 1 block. -An example of a simple 3D project using both extension is shown below: -```scratch -when flag clicked -enter AR mode :: #d10000 -create mesh [my mesh] :: sensing -set [my mesh] from [obj mtl v] [my 3D model v] :: sensing -forever -configure [to projected from view space v] transformation :: sensing -start with (AR: view to projected v) :: sensing -configure [to view space from world space v] transformation :: sensing -start with (AR: world to view v) :: sensing -clear [color and depth v] :: sensing -draw mesh [my mesh] :: sensing -end - -when stage clicked -move everything by x: (hit position [x v] :: #d10000) y: (hit position [y v] :: #d10000) z: (hit position [z v] :: #d10000) :: #d10000 -``` \ No newline at end of file diff --git a/docs/steamworks.md b/docs/steamworks.md deleted file mode 100644 index b87fad810a..0000000000 --- a/docs/steamworks.md +++ /dev/null @@ -1,99 +0,0 @@ -# Steamworks - -The Steamworks extension lets you use these Steam APIs: - - - Basic user information (name, id, level, country) - - Achievements - - DLC - - Opening URLs in the Steam Overlay - -This extension was not created by and is not supported by Valve. This extension should be considered **alpha** until some real games use it. - -## Enabling Steamworks - -The Steamworks SDK will be automatically downloaded and enabled when a project using the Steamworks extension is put into the [TurboWarp Packager](https://packager.turbowarp.org/). You'll be asked to provide your game's App ID, which you can find on the Steamworks website. If you don't have an App ID yet, [use the demo game](#demo-game). You will also need to select one of these environments: - - - Electron Windows application (64-bit) - - Electron macOS application - (Warning: macOS games published on Steam need to be notarized by Apple, which the packager doesn't support. You can still test your game on a Mac, but you won't be able to publish it for macOS yet.) - - Electron Linux application (64-bit) - -You may have to look under "Other environments" to find some of these. The blocks will not work in the editor, 32-bit environments, ARM environments, plain HTML files, WKWebView, or NW.js. You can still run the blocks, they just won't interact with Steam at all. - -You can run the packaged executable directly as usual; you don't need to start the game from Steam for the Steamworks extension to function. However there are a couple caveats when doing this: - - - On macOS and Linux, when not started through Steam, the Steam Overlay may not work - - On Linux, when not started through Steam, Steamworks may not work if Steam is installed from Flatpak/Snap instead of as a native package - -## Security considerations - -Using the Steamworks extension will not prevent people from pirating your game. - -The Steamworks extension is also inherently client-side, so a cheater could manipulate all of the Steamworks blocks to return whatever they want. You shouldn't use them for things that are security critical. - -## Demo game - -To test the Steamworks extension without paying for a Steamworks Partner Program membership, you can use the Steamworks demo game. It's called Spacewar and its App ID is `480`. You don't need to install or run Spacewar; rather, you can use its App ID to test various Steamworks APIs as if you were the Spacewar developers. - -Spacewar has achievements with the following API Names, which can used for testing the achievement blocks: - - - `ACH_WIN_ONE_GAME` - - `ACH_WIN_100_GAMES` - - `ACH_TRAVEL_FAR_ACCUM` - - `ACH_TRAVEL_FAR_SINGLE` - -## Basic information - -Remember that Steamworks is only properly enabled when your project is packaged in a few specific environments. You can detect if this is the case using: - -```scratch - -``` - -Then you can get basic information about the user using: - -```scratch -(get user (name v) :: #136C9F) -``` - -## Achievements - -Achievements are created on the Steamworks website. The **API Name** of each achievement is what you need to provide in your project's code to the Steamworks extension. - -This would unlock the `ACH_WIN_ONE_GAME` achievement from Spacewar: - -```scratch -when this sprite clicked -set achievement [ACH_WIN_ONE_GAME] unlocked to (true v) :: #136C9F -``` - -You can also detect if an achievement has already been unlocked: - -```scratch -when flag clicked -forever - if then - say [Unlocked!] - else - say [Not unlocked :(] - end -end -``` - -## DLC - -Each DLC has its own App ID which you can find on the Steamworks website. You can detect if it is installed using: - -```scratch -if <(DLC v) [1234] installed? :: #136C9F> then - -end -``` - -## Overlay - -The Steamworks extension has a block to open URLs in the Steam Overlay's web browser. If the overlay is not working, it might open in the Steam app instead. If that also doesn't work, it will open in the default web browser. Regardless, packaged projects never display security prompts like "The project wants to open a new window or tab". - -```scratch -open (URL v) [https://example.com/] in overlay :: #136C9F -``` diff --git a/extensions/-SIPC-/consoles.js b/extensions/-SIPC-/consoles.js index 5c7b2a1ace..032af4ddd4 100644 --- a/extensions/-SIPC-/consoles.js +++ b/extensions/-SIPC-/consoles.js @@ -35,10 +35,7 @@ arguments: { string: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate({ - default: "Log", - description: "Default value", - }), + defaultValue: Scratch.translate("log"), }, }, }, @@ -49,10 +46,7 @@ arguments: { string: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate({ - default: "Information", - description: "Default value", - }), + defaultValue: Scratch.translate("Information"), }, }, }, @@ -63,10 +57,7 @@ arguments: { string: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate({ - default: "Warning", - description: "Default value", - }), + defaultValue: Scratch.translate("Warning"), }, }, }, @@ -77,10 +68,7 @@ arguments: { string: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate({ - default: "Error", - description: "Default value", - }), + defaultValue: Scratch.translate("Error"), }, }, }, @@ -91,10 +79,7 @@ arguments: { string: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate({ - default: "Debug", - description: "Default value", - }), + defaultValue: Scratch.translate("Debug"), }, }, }, @@ -107,10 +92,7 @@ arguments: { string: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate({ - default: "Group", - description: "Default value", - }), + defaultValue: Scratch.translate("group"), }, }, }, @@ -123,10 +105,7 @@ arguments: { string: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate({ - default: "Group", - description: "Default value", - }), + defaultValue: Scratch.translate("group"), }, }, }, @@ -144,10 +123,7 @@ arguments: { string: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate({ - default: "Time", - description: "Default value", - }), + defaultValue: Scratch.translate("Time"), }, }, }, @@ -158,10 +134,7 @@ arguments: { string: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate({ - default: "Time", - description: "Default value", - }), + defaultValue: Scratch.translate("Time"), }, }, }, @@ -174,10 +147,7 @@ arguments: { string: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate({ - default: "Time", - description: "Default value", - }), + defaultValue: Scratch.translate("Time"), }, }, }, diff --git a/extensions/-SIPC-/recording.js b/extensions/-SIPC-/recording.js index 82d2bebb55..b4bc74f081 100644 --- a/extensions/-SIPC-/recording.js +++ b/extensions/-SIPC-/recording.js @@ -18,14 +18,14 @@ { opcode: "startRecording", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("start recording"), + text: Scratch.translate("Start recording"), blockIconURI: icon, arguments: {}, }, { opcode: "stopRecording", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("stop recording"), + text: Scratch.translate("Stop recording"), blockIconURI: icon, arguments: {}, }, @@ -33,7 +33,7 @@ opcode: "stopRecordingAndDownload", blockType: Scratch.BlockType.COMMAND, text: Scratch.translate( - "stop recording and download with [name] as filename" + "Stop recording and download with [name] as filename" ), blockIconURI: icon, arguments: { @@ -50,7 +50,7 @@ { opcode: "isRecording", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("recording?"), + text: Scratch.translate("Recording?"), blockIconURI: icon, arguments: {}, }, diff --git a/extensions/-SIPC-/time.js b/extensions/-SIPC-/time.js index e23c3e95ea..97ae135b5e 100644 --- a/extensions/-SIPC-/time.js +++ b/extensions/-SIPC-/time.js @@ -50,7 +50,7 @@ { opcode: "Timedata", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("[Timedata] from [timestamp]"), + text: Scratch.translate("get [Timedata] from [timestamp]"), arguments: { timestamp: { type: Scratch.ArgumentType.NUMBER, diff --git a/extensions/0832/rxFS.js b/extensions/0832/rxFS.js index 4191496066..ad0969d447 100644 --- a/extensions/0832/rxFS.js +++ b/extensions/0832/rxFS.js @@ -30,7 +30,7 @@ blockIconURI: wenj, opcode: "start", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("new [STR]"), + text: "New [STR] ", arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -42,7 +42,7 @@ blockIconURI: wenj, opcode: "file", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set [STR] to [STR2]"), + text: "Set [STR] to [STR2] ", arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -50,7 +50,7 @@ }, STR2: { type: Scratch.ArgumentType.STRING, - defaultValue: Scratch.translate("rxFS is good!"), + defaultValue: "rxFS is good!", }, }, }, @@ -58,7 +58,7 @@ blockIconURI: wenj, opcode: "sync", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("change the location of [STR] to [STR2]"), + text: "Change the location of [STR] to [STR2] ", arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -74,7 +74,7 @@ blockIconURI: wenj, opcode: "del", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("delete [STR]"), + text: "Delete [STR] ", arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -86,7 +86,7 @@ blockIconURI: wenj, opcode: "webin", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("load [STR] from the network"), + text: "Load [STR] from the network", arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -98,7 +98,7 @@ blockIconURI: wenj, opcode: "open", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("open [STR]"), + text: "Open [STR]", arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -110,14 +110,14 @@ blockIconURI: file, opcode: "clean", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("clear file system"), + text: "Clear file system", arguments: {}, }, { blockIconURI: file, opcode: "in", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("import file system from [STR]"), + text: "Import file system from [STR]", arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -129,16 +129,14 @@ blockIconURI: file, opcode: "out", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("export file system"), + text: "Export file system", arguments: {}, }, { blockIconURI: file, opcode: "list", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate( - "list the contents under the same folder [STR]" - ), + text: "List the contents under the same folder [STR]", arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -150,7 +148,7 @@ blockIconURI: file, opcode: "search", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("search [STR]"), + text: "Search [STR]", arguments: { STR: { type: Scratch.ArgumentType.STRING, diff --git a/extensions/0832/rxFS2.js b/extensions/0832/rxFS2.js index 4e631709b9..d321fa9ac8 100644 --- a/extensions/0832/rxFS2.js +++ b/extensions/0832/rxFS2.js @@ -38,7 +38,7 @@ blockIconURI: file, opcode: "start", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate({ id: "start", default: "create [STR]" }), + text: Scratch.translate({ id: "start", default: "Create [STR]" }), arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -52,7 +52,7 @@ blockType: Scratch.BlockType.COMMAND, text: Scratch.translate({ id: "folder", - default: "set [STR] to [STR2]", + default: "Set [STR] to [STR2]", }), arguments: { STR: { @@ -74,7 +74,7 @@ blockType: Scratch.BlockType.COMMAND, text: Scratch.translate({ id: "sync", - default: "change the location of [STR] to [STR2]", + default: "Change the location of [STR] to [STR2]", }), arguments: { STR: { @@ -91,7 +91,7 @@ blockIconURI: file, opcode: "del", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate({ id: "del", default: "delete [STR]" }), + text: Scratch.translate({ id: "del", default: "Delete [STR]" }), arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -105,7 +105,7 @@ blockType: Scratch.BlockType.REPORTER, text: Scratch.translate({ id: "webin", - default: "load [STR] from the web", + default: "Load [STR] from the web", }), arguments: { STR: { @@ -118,7 +118,7 @@ blockIconURI: file, opcode: "open", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate({ id: "open", default: "open [STR]" }), + text: Scratch.translate({ id: "open", default: "Open [STR]" }), arguments: { STR: { type: Scratch.ArgumentType.STRING, @@ -133,7 +133,7 @@ blockType: Scratch.BlockType.COMMAND, text: Scratch.translate({ id: "clean", - default: "clear the file system", + default: "Clear the file system", }), arguments: {}, }, @@ -143,7 +143,7 @@ blockType: Scratch.BlockType.COMMAND, text: Scratch.translate({ id: "in", - default: "import file system from [STR]", + default: "Import file system from [STR]", }), arguments: { STR: { @@ -158,7 +158,7 @@ blockType: Scratch.BlockType.REPORTER, text: Scratch.translate({ id: "out", - default: "export file system", + default: "Export file system", }), arguments: {}, }, @@ -168,7 +168,7 @@ blockType: Scratch.BlockType.REPORTER, text: Scratch.translate({ id: "list", - default: "list all files under [STR]", + default: "List all files under [STR]", }), arguments: { STR: { @@ -181,7 +181,7 @@ blockIconURI: folder, opcode: "search", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate({ id: "search", default: "search [STR]" }), + text: Scratch.translate({ id: "search", default: "Search [STR]" }), arguments: { STR: { type: Scratch.ArgumentType.STRING, diff --git a/extensions/CST1229/images.js b/extensions/CST1229/images.js index 2828078037..43b33ccd0a 100644 --- a/extensions/CST1229/images.js +++ b/extensions/CST1229/images.js @@ -1,9 +1,3 @@ -// Name: Images -// ID: images -// Description: Some blocks for working with images. -// Original: CST1229 -// License: MIT - (function (Scratch) { "use strict"; const QueryImage = { @@ -34,7 +28,7 @@ getInfo() { return { id: "images", - name: Scratch.translate("Images"), + name: "Images", blocks: [ { opcode: "getImage", diff --git a/extensions/CST1229/zip.js b/extensions/CST1229/zip.js index a8b88b37e3..87efc5de90 100644 --- a/extensions/CST1229/zip.js +++ b/extensions/CST1229/zip.js @@ -21,10 +21,6 @@ this.zipPaths = Object.create(null); this.zip = null; - // for developers who want to integrate their extensions with this one - // @ts-ignore - Scratch.vm.runtime.ext_cst1229zip = this; - this.zipError = false; Scratch.vm.runtime.on("RUNTIME_DISPOSED", () => { diff --git a/extensions/CubesterYT/KeySimulation.js b/extensions/CubesterYT/KeySimulation.js index 7b2265b88d..795be1fd7a 100644 --- a/extensions/CubesterYT/KeySimulation.js +++ b/extensions/CubesterYT/KeySimulation.js @@ -7,7 +7,8 @@ (function (Scratch) { "use strict"; - const icon = `data:image/svg+xml;,${encodeURIComponent(``)}`; + const icon = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAAXNSR0IArs4c6QAAFs9JREFUeF7tnXuwZMVdxz9n5t67e++CSGBFMMSERzAkGB9EjVHDkrA8AlSy0TxUqsRS4+MPqmI0CbDcvssjkFSMVlnRwtJYqVAQNGAJRBN3F4gkmhAMiJiEd4wGMYCBsK97986xvuecHnr6njPTM3POmYe3q6Zmd26f7v51f8+vf/3r3yNiCouBFwOviuD4GI6N4MX6Bl4EHKpPBIfGEAMt0u+DwP/qE8EzMXwbeBx4LILHVuDBK+CxaZuuaNIJugo2L8PrgNdF8JpWuvBHVEFXDE834N4Y7ovgC/vhcx9IgTKxZSIBYOA04GzgHL3pI579fwE+B9xiYPeIx9J39xMDgCU4I4Z3AOcDR/ZNaT0PPCkgADcb+HQ9XQ7Xy1gDwMAJwIWkC39cKKmzwEL22QjoMwfo95ns0wAs8VYQWAVWss8ysD/77AP2ZL+HjgF4BPjEQbjuCnioj+dqrTqWAFiCLTG8C3h7yGx8D3AYoO9DsgUPea7fOgLE88BzwLPZd2AbfwV81MAdgfVrqzZWAFiC82J4D/Bz3WZAb7OkPIn0hwPN2qarsyNxDB0bngGeBsQ1upUIbo/hjw3cNKIhr+l2LABg4CzShX9D0cRokb8P2Jwt+iATuCXwodsD6/nVBAYdCf4HEDi6lF0tuGYH/MOAXZX22EgBYOCHgB3ALxRRJLZ+NHCUs2cPSn3VALDjkkwhafC/s62iy3hvXoXtl8MDg9I07HMjA4BJF357EQF6048BvndYCp3n6wKAO+TvAN/KOEMXUpYMmBJJDW6qdgAYeCPwkaLzu9i81HhS15VdRgEAS8N3gf/Mtoc8uiJ4QPKPgb8vm+5u7dUKAAPXAL+fNyAJcz+YSfNVTcAoAWBp0unhPzLBsYDOawy8r6o58NutBQA74JQW/Bnwk/4AdEZ/WSbgVU30OADA0ihBURcLOlrmlH8GfseAtIyVlsoBsAQXxHBt3vFcrF7ancoHkU3hOAFAQ5Kw+Gi2NeSssnRSv2rgE1UioNK5L2L50tJJxSe2X2cZNwBY2nV8fBjYmz8ZHzBwcVXzVBkAMuT+kj9wHelOrPGtd/sfVwBYbiB98RP5K32DgXdWAYLSAXAlHLUC1wNr5vvl2Zm+CkJC2hxnANjx68hYcHGwC3ibSRWPpZVSAXAJHDsLfwv8iDtCCXrS+EhfP8oyCQDQ/Oik8LUcATGC+2LYZlLRoZRSGgAuh5etpovfcT+vRX8FsKGU4Q7XyKQAQFQeyEAgRZJX/h14k0mtlYYupQAgW/y/A05yRyRt3slDD7G8BiYJAJZqrXaOydEDM/CmS+Ebw87O0AAwqbZW+9OPuYP5fh8Nw460hOcnEQAi++vZvYI7BRHcPwtbLk4vIgcuZQBgp3+LJ0lfAt+4lUkFgObxwfwTwq5MtT7wVA8FgCW4MfZu8sbxzbezM8kAKOIEwPUGfnFQBAwMAANXAJeM857vT8qkA0D0FMgEVxt4/yAgGAgAmXr3426HEgRePcgIanxmGgCg6bo3387ggkHUxn0DwKRn/HsA2VUmRed8/TgOR71ueJoWAOiIKBC4F0kRHIjhp0z6p+AyCAA+D/y024MWf9RKnhCKpwUAolXKopyV/pLJuXHtNjd9AcDA1cB73Qal15flzjgV2ePJ38sSZ79liRJSBrUJDGm7zDq6N9DpwCt92RMEA8CkXji3uZ2N03Ev9O0OWQBrZazJkcNgXhkXkBQcD8808NkQWvsBwH3AD9tGdaV76ohu9YoIKxME3SZvXBZfY5RNwZe9q+QIvroYqIQNAkBmsLjoToqQUPd9fgiiqwbBOC2+nQ/ZE/zr2skJMjTtCYDt8OqmJ2/Ikuf4kNUYUZ2qQDCOi2+nWH5oMjr1yitNqjooLD0BYOBG125fR76fGDPWn0dd2SAY58W3W8GX1l4h32TgrQMDINMzd3iv6GpXptuTUMoCwbgvvl0LGZp+1VuYCLYudvFA6soBlmB37Fj2yBfvlElYeWeMw4JgUhbfknz/WpPzrhdGhQAw8Gb5ubvrPSkKHx+jg4Jg0hZfdBcoiN5i4G/y3t1CACzBzthx1hTbF/uf1NIvCCZx8e3aaBvQduCUO0yOjab+ngsAA6dnRh7tNmTtUYW7Vp2ACgXBJC++5lNuaDkeJVvy4hMUAUD+62+xizNupl3DgKYXCCZ98e3c5Fwb32hyAm6sAUBm39dhdapr3jK9dIdZwDKeLQLBtCy+5kjGpFLdeuUk410frAGAr/WTf/6PljHrY9aGD4JpWnw71V9ZG8Zmh4EOje4aACzCo1Hqr5kUmfnKzGvainToEnRUpnHxRZcCVMig1CkPm9Qxq106AJCFapF5d1J0K6YIjD3VhdOGjimhRyCX8YYXruZsNwaBD4A/JY3OlZRxuu6dkjWpnYyc6+I/N/BrdiA+AMQ1FI4nKeN641f7LE5whzk3hU8aZ1dvA8DAVuAzllaFYnvtGBEezSjEo/ajFzAbOf/uOtTQen4jsZhofyV2n4lj4tVVGKCd/nrtXvufvBB2EZy+mIk+LgA+CPzeOvsvc+ph7thjWf7mN8tttM/WcraBPzDwu8n7ZNsycHdm5JP89MoRB+RtzM3RWl5m7uijWX7iCc6fmeFgS5Z+adG7qcHbd9T+u9tvVfzNTmIyDr3x2ff8/Dw371OQ2bQ0N21idY8CztZfnqIzDl0EX1nMXPkSAJj0hleh7drlZ0YYgZOZGbYcPNhxPNvabLIiduqVRqNBKwNGs9lM/i02rN/1rc+MwHPwBes++4y/hXSwb6cf1bN/Ux+rOeOw1W3dRhSxy2H90jvcdcQRrDw9lCvfQOjRrN219snNBp5KALAEb4/hBltHJt4dDv4DdTvYQ3EUcXo2ce75XGf2vB3ZLroWeWVFYXUkJqSMTYs2Ozvb/t0Fi/23nhNo9HEX2h29/d1+z83NsbzcPTCs6u72AKA2dzWbNLoAaLBZ6/2UrxSKYNsi3Gw5QEf4NqXWCA7N3bvv8BqNBluyt/mYmRmuc97arVHESo4wZRdFC6lFFQi08C4ILCgsZ7AcwwdLyEAtNykCi20jjwPYv93ebELNIJBu35NEPmLg3RYAsvppm82PZP+PIrY4C/yiRoNPOXv+uTMz7HEA4bJcu9h2USzrd7eBkMUNreNyEv8Zl1v4HGDWAXHd2kdfDgB2G3iDBYDizrSNfBXMT7Z/dRZXNz/baLAhjrnFAcS5UcSeHA6wYcOG5K3XW92MokQwXLXCWJ0EeH114wBtTlDj+ORG9sXO/p4ysDkyKbeXUWlSlFShw++rhkG6i39Yo8GzrRaboohbnQU/J4rY12ULcFmyK+2XNXxXY9ZNO9BNCNTf5FApgI4CBF/wkl7MwEujLBVL24ukbi9f/1YuyeTRbLKx1eoAwBldvHTKWuRe7VgQhACgSAjU71KyHRgBCHyv4gjOEQf4TeBPLPF16/9dAMxEES19Wi3mo4hPO5MkAaVHDP5e6zf030M4SzcO4Aqj7mDqkgdyFEK/JQB8KEvWkIxJ98AvGXqqwhuwABDrf05Cn9hko8Fcq9UBgKJjYHhP9dTsJgS6AJCcs5IJubsbDSJH4K1qpApS7SU+vEYA0Pm/nZunTrt/98yvt6vhKHLGkQOELEw/HGAhitgbx9y1eTMr364+/WCO38ANAkBHkKc6zb9WNm5k6/79SWAJqVXcvdUHgHLJvKAIDlmK0dQJBYDqRXGc0FTXFpBjJnanACDZoB3dRR6/m2qau+WFBc7cuzc5eaQ6vBfKtAMg2Q4y0NcFAN1EyJPYFkUeFQDkU/gD9kddAUtKraMcWFjgrEAAjIMQGDInoRxgFABQaBklInAA8A0BQDYDbaPfOi+BLAB00+8HYvA5wLQJgS6Y6uIA/qVQBM9Gi/B85HB9JeyrywbwwKZNnLVnT5LNsxcAppEDWBDUBQDJWEpy7JQD4gDiDG2u//oQPldSnX4AMGlCYDdFkH/tXBcAtGx3dq7dQQFAnKEd8m0dAMOhux8ZoG4OkAOAWKrgvTHM28GsbwHTCwB/C4hgn2QAWYUoFW9S6hQC9y8scPbevYn/ga/mnfRj4DhuAb4QGMPT2gIUc76t/a31GBggBM6fcAL7Hn44MVYY9V1ACG8Y5y3APwbKRkQAkDu5MrokpU5FkBUCu3GA+eOPZ98jjyRZpSdJExjCAUatCFJSEgFgt5vgqU5VcMgpwAJgGjlA3QDIUQXvFgCUmLCd3q3Oy6B1AKT3H3UdA3Mug64TADocQuq8Dg4RAuePO459jz66vgWECCA96uRcB39Ix8CLYvhD+2ydBiEhHMCOa30LGB4BOQYhF43UJCyEA1iy14XA4QGgiCFuGjrFENQWoMivbZPxOo1C1zlAvTKAbxS6Ai+xZuEdN4J1mYWvA6A+AOToAL5j4HDrGnZHDO1rgLocQ0L0AOtbwPCsXy3kOIbcaeA0C4CrYycTSF2uYescoD4OkOMalmQWsVtAR1jYupxD14XA+gDgO4e2YNsOxzlUgcA6UtfXcSnUDweYtFNAkWtYngdT1YqgPPfwWTjmEnjCDRAhkLS9wuuQA6YZAPJT3JnjHu4CQEYYbatgubRXFEqmZ4AICQl+RrA6FELTLASGcAAXAHKHS+IJVVByFEDtzGJtDrAEW+L0YigpdQSJCuEA8yeeyL6HHpo4VXAIB7BzrS1AQbDiHPf3MvAQFCQq4wId+oCqw8T1IwT2CvJcxkSV0Uaoa5jbVwKAijhATpi45Pxv+/fjBF4L/Hpd9wIhHGBS9QAhW4DLAZLwdxXIADns/1rjBAP1AaA7l3aOoKpDxU4zAEIMQjoAUAb78dooCBV7RuYOmNRe4wJgUgfSl9q2Xp6FjK1gfKwDIJ3Vqo6BOcGiHzdOIPAiAFwJXGwXvMpw8SEAmFQhcBw4QE64+CsNXOq+zGs4QJ0JI7oJgQuNBrcpUERmFHq6E6uvCm5UVps2MJUAsMvx+bdCbF7gqio4QF7CiCYct90LEZDrBebHDKgqZUw3DtAGQHYMnBSDEAHJxiZ0F7bbKaYKAAycMkYE+HGD9FsVSaO6KYI2NZvc6ihG3qjQMWMQ/asXp1AcQRW5f+10xi8A2BiDfpi5sgGQlzSqKIFkoR+ogV1OUo0klmzZaeO6cQCFqVPmCmsV/OaZGfatriaOpIoloG9rJp6EhtObl8Xhs+nf9Xf9W46nNgaB+zdp4vQ3/eZOhNqyDqv6dn3n3H7cMdi21M9yHDPXbHKbBwABww9bW4UQmJM2LokJmAfebgA4F7jFfajsxJHdAHDI7Cy3rKwwe+SRrDwlbfZkF3EA++ZXyQEKEkeeZ+DWvgCgyr7PQNmpY60QqOhgerNG6TVbNbwEAD98bRV6AKWRl/bPKYVJI3OPge6TBs4BbnN/K9NvwHIAse7VLDycG43b7o0hamA9V1S6RfeueuFdGuwW5QawLnMLKEgefc5iupvmlp6xIPwTQZnp4y0AtF8ur65iF3+u0WC51UoUJCGLX/Ui9tt++z7AiQHkHgPdYNVlAUBav5z08Z808I5u4+8JgEvhFTOgU0W7yIz4+H5nJae+ywFsJHD3vtwFQLcAzSUMpZQm2o6hWQ4D+3+XCySBGJwcB2UBQLF+FezJLU04efvajPIddXoCQLUNXAW8332yjJtCfwtQ+/bt6If9l7J6FTfSDczDHgNzbvxEzQeMo9EdeAuwDy7BvbETTm4h8yQOQlBB71YI1N6o45grBPrsfxI4QPpypxlMfIGvgwtkOg2fQwyCQbF+hX7b2/nwfSYw50fw+pk0n0D7plD9DWs1ZDnAhmaTA541jAVASHzeQSZuFM/4oC4DADnXvSKt48ZvKBnAfdjAh4F3u78pD+kxA86mBYD/uPu22DdJdYpy+gzYfW2PWeHWp8vSM+gW8C3gobVUtDOChRAYzAFsYybNRtqRUmBQBVE3ALjSf9H5OYTAUddxhVqNxXKB2WYzyYImEAwCgAKFz+dNGuUnuAwCgFcB97ih5XQ0FAgU87efsjw/z5lOajU7Qfq2ihPtqaM8x/dDT1FdcYBYiamyxbbgHnQLkJuX4vsqC4gtkVIQwKkG/q2fMfcNADVu4FeAj7kdDZJowgaLdtvx98leadr6IXZUdYuUW4NGCPETP2R0XWjgL/ulcSAAZCBYczTs99r4wPw8ZzkcoGOPLEgT1y+Bo67vGom6e764gDim3uZ+toCca16ReJWBSwahdWAAZCDoCC+j3+RidFLgSGysYFt9UjV/IeS6x1hfxxEKgK8DMvPyynUGfjlkDHl1hgJABgKFn/1Zt/HQ46EvBLYFJCWBrMhGftCJGuY5N6NpHthDAFBw3LvLeHPf7ziHBsBVcMQKfCaGH3c7D+EELgcoOiL1S9A41rfbgGwBlCRCKXBdensBoODNv2cOzrwYhspFOzQAMi6g6wGlnj/ZXYAQmUB7oc8SJ0XrFwo2aweo+gKDq+526c9rr2DP189nZrkeQoeRW68UAKjlS+HEWbgl9kQAuZrrCrnXEdEejWZ0Pl5dbatS3VG7SqGhqK7w4TxlVZECS8Dff+SRLOzfT+v55ztGpRQ6WmWd970ihnC+Ae0KQ5fSAKCRLKYxZz7lpqHX79ITKBSpwJBXXKWPPGp0Xq5b+VOmyrmfsStjmDyCtDXYokX/mnfOz/725RnYdumaNMCD46BUAGgY74PDN8JNwGn+sHwnk7jRoLmwwOsd9AsAyRuTpYEVGBLWmR0L/e/BSe98Us6w6snGzZdtn/rS79aLV2+l7BFla2gTXISEr/XHbNvTCPz9v0C9q6p37IdtV68x+BluBkoHgIZjYCaCj8fwTn94OiHo/qCSjoebi5E+LfBJr98RpeOFEV1/MlzwtgriZVe6DgauIEdBoavkE5xs1bM15c0b6QrndN447DBazz6b2PA9vPZK1z6xxpunTDoqBYAGugQXxiCv49Rg3ik6OihzdeWDKHPGSmxLb72CN/mWPFkX2mXeZeAvSuxyTVO1zP0OOKUFH83yUXQMQgKi4hPL7+D/U5EBp7xw3Qsdh/67GvDbl8H9Vc9JLQCwRPh5il3iZHKurBVFJ4WqJ6Ku9iXhK2jzM8UdftjAe+oaT60AEFEGtpJGKG9nK3WJFSfQ1nBoXTNQUz9y1xKr15tfUHTJ914Dn61pSEk3tQPA4QY7gO1FxEqLKEujdkbLOmelxL7kpaujXY/U0FeYLnNR4nBGIwMUEWBAxiXyV29nL/frKj6Bjo5HjRKtfa6AhLsns5u7HE2e29onG3D5ZfBAn12UVn1kHMClINsWBISOW0W3jvx+tD2IM7QjHJU2DeU0pOOc3nSx+W4B3yL4xxj01tfK7vOoHAsA2IEtwXkxXESBJ6utJ+2c8txJcBQYip3CylnYola0yFp0CXS6kpOmsEfZFcEfLXpOt70eqvLvYwUAS+hlcEYDfgP4+RDidXLQVqHPIdndQ8hz/dbRkU1XNs9lnx7s3W3+ryO4dtEzq++3/yrqjyUALKEmDVZ1YfZREPOgIj3+JsUWyMAgXYO4hn6XNkof6eMt8dqzpdPXGy1dvz56m7Xg+uwD9mS/Bw0grSShX0qcjxl4vI/naq061gBwZyKLWrINeGsmCtQ6UYGdKZCB3vabxvFtH3sZIHCSpUuQl5L9dFgihbZRVr0I7olhJ7DTjb9XVvtVtzMxHKBoIgwcE8FrY3hNBKfqOxMHSp+7CL4bw92ZJ/bdK/DFK+G/Su+oxgYnHgB5c5UZpsj8QB9dPEqNYD86PGyMYEOcfqvY7X5/nAr29hivb3lePxjDg0upFneqyv8BC0K+o6SYlTUAAAAASUVORK5CYII="; // This is from the Scratch Addons gamepad addon, which normally could be a problem because it is GPLv3, // but I (GarboMuffin) wrote that code so there is no problem. diff --git a/extensions/CubesterYT/WindowControls.js b/extensions/CubesterYT/WindowControls.js index ff1ea7d3c9..c77618d651 100644 --- a/extensions/CubesterYT/WindowControls.js +++ b/extensions/CubesterYT/WindowControls.js @@ -19,32 +19,6 @@ return Math.floor(Math.random() * (max - min + 1)) + min; } - const isFullscreenEnabled = () => { - if (typeof document.fullscreenElement !== "undefined") { - return document.fullscreenElement !== null; - } - if (typeof document.webkitFullscreenElement !== "undefined") { - return document.webkitFullscreenElement !== null; - } - return false; - }; - - const enterFullscreen = () => { - if (document.documentElement.requestFullscreen) { - document.documentElement.requestFullscreen(); - } else if (document.documentElement.webkitRequestFullscreen) { - document.documentElement.webkitRequestFullscreen(); - } - }; - - const exitFullscreen = () => { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } - }; - class WindowControls { getInfo() { return { @@ -541,17 +515,17 @@ return document.title; } enterFullscreen() { - if (!isFullscreenEnabled()) { - enterFullscreen(); + if (document.fullscreenElement == null) { + document.documentElement.requestFullscreen(); } } exitFullscreen() { - if (isFullscreenEnabled()) { - exitFullscreen(); + if (document.fullscreenElement !== null) { + document.exitFullscreen(); } } isFullscreen() { - return isFullscreenEnabled(); + return document.fullscreenElement !== null; } closeWindow() { const editorConfirmation = Scratch.translate({ diff --git a/extensions/Eaielectronic/Finger-mutli-mobile.js b/extensions/Eaielectronic/Finger-mutli-mobile.js deleted file mode 100644 index 311a103acb..0000000000 --- a/extensions/Eaielectronic/Finger-mutli-mobile.js +++ /dev/null @@ -1,172 +0,0 @@ -// Name: Finger ios/android -// ID: multiTouchDetection -// Description: Detect multiple fingers on mobile devices. Unlike sensing+ works on all mobile devices. -// By: Eaielectronic -// By: SERPENT1867 { - const canvas = Scratch.renderer.canvas; // Récupère le canvas de Scratch - const rect = canvas.getBoundingClientRect(); // Récupère la position du canvas - const scratchX = ((touch.clientX - rect.left) / rect.width) * 480 - 240; - const scratchY = 180 - ((touch.clientY - rect.top) / rect.height) * 360; - return { x: scratchX, y: scratchY }; - }; - - const touchHandler = (event) => { - // Met à jour les coordonnées des doigts dans le tableau - for (let i = 0; i < event.touches.length && i < 10; i++) { - const touch = event.touches[i]; - const { x, y } = convertToScratchCoords(touch); - this.touches[i] = { x, y }; - } - - // Réinitialise les positions restantes si moins de doigts - for (let i = event.touches.length; i < 10; i++) { - this.touches[i] = { x: 0, y: 0 }; - } - }; - - window.addEventListener("touchstart", touchHandler); - window.addEventListener("touchmove", touchHandler); - window.addEventListener("touchend", touchHandler); - } - - // Obtenir la position X du toucher d'un doigt donné - getTouchX(args) { - const index = Math.max(0, Math.min(9, args.INDEX - 1)); // Limite à 10 doigts - return this.touches[index].x; - } - - // Obtenir la position Y du toucher d'un doigt donné - getTouchY(args) { - const index = Math.max(0, Math.min(9, args.INDEX - 1)); // Limite à 10 doigts - return this.touches[index].y; - } - - // Nouveau: Obtenir la position X d'un doigt touchant un sprite - getTouchXOnSprite(args, util) { - const spriteBounds = util.target.getBounds(); - - // Cherche le premier doigt touchant le sprite et renvoie sa position X - for (let i = 0; i < this.touches.length; i++) { - const touch = this.touches[i]; - if ( - spriteBounds.left <= touch.x && - touch.x <= spriteBounds.right && - spriteBounds.bottom <= touch.y && - touch.y <= spriteBounds.top - ) { - return touch.x; - } - } - return 0; // Retourne 0 si aucun doigt ne touche le sprite - } - - // Nouveau: Obtenir la position Y d'un doigt touchant un sprite - getTouchYOnSprite(args, util) { - const spriteBounds = util.target.getBounds(); - - // Cherche le premier doigt touchant le sprite et renvoie sa position Y - for (let i = 0; i < this.touches.length; i++) { - const touch = this.touches[i]; - if ( - spriteBounds.left <= touch.x && - touch.x <= spriteBounds.right && - spriteBounds.bottom <= touch.y && - touch.y <= spriteBounds.top - ) { - return touch.y; - } - } - return 0; // Retourne 0 si aucun doigt ne touche le sprite - } - } - - Scratch.extensions.register(new MultiTouchDetection()); -})(Scratch); diff --git a/extensions/Eaielectronic/Fps-returne.js b/extensions/Eaielectronic/Fps-returne.js deleted file mode 100644 index 2d7ce09a71..0000000000 --- a/extensions/Eaielectronic/Fps-returne.js +++ /dev/null @@ -1,77 +0,0 @@ -// Name: FPS returne -// ID: fpsbasedreturn -// Description: allows you to create games that run at the same speed, even if the FPS changes. -// By: Eaielectronic -// By: SERPENT1867 -// License: MPL-2.0 -(function (Scratch) { - "use strict"; - class FPSBasedReturn { - constructor() { - this.previousTime = null; // Pour stocker l'heure de la dernière frame - this.fpsValue = 30; // Initialiser avec une valeur par défaut (30 FPS) - } - - getInfo() { - return { - id: "fpsbasedreturn", - name: "FPS Based Return", - blocks: [ - { - opcode: "getFPSMultiplier", - blockType: Scratch.BlockType.REPORTER, - text: "FPS multiplier (based on [REFERENCE] FPS", - arguments: { - REFERENCE: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 30, - }, - }, - }, - { - opcode: "getCurrentFPS", - blockType: Scratch.BlockType.REPORTER, - text: "current FPS", - }, - ], - }; - } - - // Méthode pour obtenir le delta time et calculer une fois les FPS - calculateFPS() { - const currentTime = performance.now(); - - if (this.previousTime === null) { - this.previousTime = currentTime; - return; // Attendre jusqu'à la prochaine frame pour calculer le delta time - } - - let deltaTime = (currentTime - this.previousTime) / 1000; // Convertir en secondes - this.previousTime = currentTime; - - if (deltaTime > 1 / 30) { - deltaTime = 1 / 30; // Limiter à 30 FPS max pour éviter des pics - } - - this.fpsValue = 1 / deltaTime; // Calculer les FPS actuels - } - - // Méthode pour retourner le FPS actuel - getCurrentFPS() { - this.calculateFPS(); // Mettre à jour le FPS - return this.fpsValue; // Retourner la valeur des FPS actuels - } - - // Méthode pour calculer le multiplicateur en fonction des FPS - getFPSMultiplier(args) { - const referenceFPS = args.REFERENCE; // FPS de référence choisi par l'utilisateur - const fps = this.getCurrentFPS(); // Obtenir les FPS actuels - - const multiplier = referenceFPS / fps; // Le rapport par rapport au FPS de référence - return multiplier; - } - } - - // Enregistrer l'extension dans TurboWarp - Scratch.extensions.register(new FPSBasedReturn()); -})(Scratch); diff --git a/extensions/Eaielectronic/ScrollingTextBubble.js b/extensions/Eaielectronic/ScrollingTextBubble.js deleted file mode 100644 index 2442876a6b..0000000000 --- a/extensions/Eaielectronic/ScrollingTextBubble.js +++ /dev/null @@ -1,276 +0,0 @@ -// Name: Scrolling bull -// ID: scrollingTextBubble -// Description: Create scrolling text bubbles and apply styles with Html tags. -// By: Eaielectronic -// By: SERPENT1867 -// License: MPL-2.0 -(function (Scratch) { - "use strict"; - - class ScrollingTextBubble { - constructor() { - this.bubbles = {}; - this.defaultBubbleStyle = { - backgroundColor: "rgba(255, 255, 255, 0.8)", - borderColor: "black", - borderWidth: "2px", - borderRadius: "10px", - boxShadow: "0 4px 8px rgba(0, 0, 0, 0.2)", - padding: "15px", // Valeur par défaut du padding - }; - } - - getInfo() { - return { - id: "scrollingTextBubble", - name: "Scrolling Text Bubble", - blocks: [ - { - opcode: "showTextBubble", - blockType: Scratch.BlockType.COMMAND, - text: "show text bubble with text [TEXT] next to sprite with speed [SPEED], font [FONT], width [WIDTH], offsetX [OFFSETX], offsetY [OFFSETY]", - arguments: { - TEXT: { - type: Scratch.ArgumentType.STRING, - defaultValue: "Hello, World!", - }, - SPEED: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 50, - }, - FONT: { - type: Scratch.ArgumentType.STRING, - defaultValue: "Arial", - }, - WIDTH: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 200, - }, - OFFSETX: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 0, - }, - OFFSETY: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: -60, - }, - }, - filter: [Scratch.TargetType.SPRITE], - }, - { - opcode: "hideTextBubble", - blockType: Scratch.BlockType.COMMAND, - text: "hide text bubble", - filter: [Scratch.TargetType.SPRITE], - }, - { - opcode: "hideAllTextBubbles", - blockType: Scratch.BlockType.COMMAND, - text: "hide all text bubbles", - }, - { - opcode: "setBubbleColor", - blockType: Scratch.BlockType.COMMAND, - text: "set bubble color to [COLOR]", - arguments: { - COLOR: { - type: Scratch.ArgumentType.COLOR, - defaultValue: "#ffffff", - }, - }, - }, - { - opcode: "setBubbleStyle", - blockType: Scratch.BlockType.COMMAND, - text: "set bubble style to [STYLE]", - arguments: { - STYLE: { - type: Scratch.ArgumentType.STRING, - menu: "bubbleStyleMenu", - defaultValue: "default", - }, - }, - }, - { - opcode: "setBubblePadding", - blockType: Scratch.BlockType.COMMAND, - text: "set bubble padding to [PADDING]", - arguments: { - PADDING: { - type: Scratch.ArgumentType.NUMBER, - defaultValue: 15, // Valeur par défaut pour le padding - }, - }, - }, - ], - menus: { - bubbleStyleMenu: { - acceptReporters: true, - items: ["default", "rounded", "sharp", "shadow", "no-border"], - }, - }, - }; - } - - showTextBubble(args, util) { - const sprite = util.target; - const text = args.TEXT; - const speed = args.SPEED; - const font = args.FONT; - const width = args.WIDTH; - const offsetX = args.OFFSETX; - const offsetY = args.OFFSETY; - - if (this.bubbles[sprite.id]) { - clearInterval(this.bubbles[sprite.id].intervalId); - this.bubbles[sprite.id].bubbleDiv.remove(); - } - - const bubbleDiv = document.createElement("div"); - bubbleDiv.style.position = "absolute"; - this.applyBubbleStyle(bubbleDiv); - bubbleDiv.style.maxWidth = `${width}px`; - bubbleDiv.style.overflow = "hidden"; - bubbleDiv.style.whiteSpace = "pre-wrap"; - bubbleDiv.style.fontFamily = font; - bubbleDiv.style.color = "black"; - bubbleDiv.style.fontSize = "16px"; - bubbleDiv.style.lineHeight = "1.5"; - - const canvas = Scratch.renderer.canvas; - const rect = canvas.getBoundingClientRect(); - - const textContainer = document.createElement("span"); - bubbleDiv.appendChild(textContainer); - document.body.appendChild(bubbleDiv); - - const updateBubblePosition = () => { - const { x, y } = sprite; - - const proportionX = rect.width / 480; - const proportionY = rect.height / 360; - - const adjustedOffsetX = offsetX * proportionX; - const adjustedOffsetY = offsetY * proportionY; - - bubbleDiv.style.left = `${rect.left + ((x + 240) / 480) * rect.width + adjustedOffsetX}px`; - bubbleDiv.style.top = `${rect.top + ((180 - y) / 360) * rect.height + adjustedOffsetY}px`; - }; - - updateBubblePosition(); - window.addEventListener("mousemove", updateBubblePosition); - - const formattedText = this.formatText(text); - const textParts = this.splitText(formattedText); - - let index = 0; - let currentHTML = ""; - - const intervalId = setInterval(() => { - if (index < textParts.length) { - currentHTML += textParts[index]; - textContainer.innerHTML = currentHTML; - index++; - } else { - clearInterval(intervalId); - } - }, speed); - - this.bubbles[sprite.id] = { intervalId, bubbleDiv }; - } - - hideTextBubble(args, util) { - const sprite = util.target; - - if (this.bubbles[sprite.id]) { - clearInterval(this.bubbles[sprite.id].intervalId); - this.bubbles[sprite.id].bubbleDiv.remove(); - delete this.bubbles[sprite.id]; - } - } - - hideAllTextBubbles() { - for (const spriteId in this.bubbles) { - if (Object.prototype.hasOwnProperty.call(this.bubbles, spriteId)) { - clearInterval(this.bubbles[spriteId].intervalId); - this.bubbles[spriteId].bubbleDiv.remove(); - delete this.bubbles[spriteId]; - } - } - } - - setBubbleColor(args) { - const color = args.COLOR; - this.defaultBubbleStyle.backgroundColor = color; - } - - setBubblePadding(args) { - const padding = args.PADDING; - this.defaultBubbleStyle.padding = `${padding}px`; - } - - setBubbleStyle(args) { - const style = args.STYLE; - - switch (style) { - case "rounded": - this.defaultBubbleStyle.borderRadius = "20px"; - break; - case "sharp": - this.defaultBubbleStyle.borderRadius = "0px"; - break; - case "shadow": - this.defaultBubbleStyle.boxShadow = "0 8px 16px rgba(0, 0, 0, 0.5)"; - break; - case "no-border": - this.defaultBubbleStyle.borderWidth = "0px"; - break; - default: - this.defaultBubbleStyle = { - backgroundColor: "rgba(255, 255, 255, 0.8)", - borderColor: "black", - borderWidth: "2px", - borderRadius: "10px", - boxShadow: "0 4px 8px rgba(0, 0, 0, 0.2)", - padding: "15px", - }; - break; - } - } - - applyBubbleStyle(bubbleDiv) { - bubbleDiv.style.backgroundColor = this.defaultBubbleStyle.backgroundColor; - bubbleDiv.style.border = `${this.defaultBubbleStyle.borderWidth} solid ${this.defaultBubbleStyle.borderColor}`; - bubbleDiv.style.borderRadius = this.defaultBubbleStyle.borderRadius; - bubbleDiv.style.boxShadow = this.defaultBubbleStyle.boxShadow; - bubbleDiv.style.padding = this.defaultBubbleStyle.padding; - } - - formatText(text) { - // Retourne le texte brut, seules les balises HTML sont interprétées - return text; - } - - splitText(text) { - const parts = []; - const tagRegex = /<\/?[^>]+>/g; - let lastIndex = 0; - - text.replace(tagRegex, (match, index) => { - if (index > lastIndex) { - parts.push(...text.slice(lastIndex, index).split("")); - } - parts.push(match); - lastIndex = index + match.length; - }); - - if (lastIndex < text.length) { - parts.push(...text.slice(lastIndex).split("")); - } - - return parts; - } - } - - Scratch.extensions.register(new ScrollingTextBubble()); -})(Scratch); diff --git a/extensions/JeremyGamer13/tween.js b/extensions/JeremyGamer13/tween.js index ea2ed20bec..224706d2c3 100644 --- a/extensions/JeremyGamer13/tween.js +++ b/extensions/JeremyGamer13/tween.js @@ -256,13 +256,11 @@ getInfo() { return { id: "jeremygamerTweening", - name: Scratch.translate("Tweening"), + name: "Tweening", blocks: [ { opcode: "tweenValue", - text: Scratch.translate( - "[MODE] ease [DIRECTION] [START] to [END] by [AMOUNT]%" - ), + text: "[MODE] ease [DIRECTION] [START] to [END] by [AMOUNT]%", disableMonitor: true, blockType: BlockType.REPORTER, arguments: { @@ -290,9 +288,7 @@ }, { opcode: "tweenVariable", - text: Scratch.translate( - "tween variable [VAR] to [VALUE] over [SEC] seconds using [MODE] ease [DIRECTION]" - ), + text: "tween variable [VAR] to [VALUE] over [SEC] seconds using [MODE] ease [DIRECTION]", blockType: BlockType.COMMAND, arguments: { VAR: { @@ -319,9 +315,7 @@ }, { opcode: "tweenXY", - text: Scratch.translate( - "tween to x: [X] y: [Y] over [SEC] seconds using [MODE] ease [DIRECTION]" - ), + text: "tween to x: [X] y: [Y] over [SEC] seconds using [MODE] ease [DIRECTION]", blockType: BlockType.COMMAND, arguments: { PROPERTY: { @@ -352,9 +346,7 @@ }, { opcode: "tweenProperty", - text: Scratch.translate( - "tween [PROPERTY] to [VALUE] over [SEC] seconds using [MODE] ease [DIRECTION]" - ), + text: "tween [PROPERTY] to [VALUE] over [SEC] seconds using [MODE] ease [DIRECTION]", blockType: BlockType.COMMAND, arguments: { PROPERTY: { @@ -383,69 +375,11 @@ menus: { modes: { acceptReporters: true, - items: [ - { - text: Scratch.translate("linear"), - value: "linear", - }, - { - text: Scratch.translate("sine"), - value: "sine", - }, - { - text: Scratch.translate("quad"), - value: "quad", - }, - { - text: Scratch.translate("cubic"), - value: "cubic", - }, - { - text: Scratch.translate("quart"), - value: "quart", - }, - { - text: Scratch.translate("quint"), - value: "quint", - }, - { - text: Scratch.translate("expo"), - value: "expo", - }, - { - text: Scratch.translate("circ"), - value: "circ", - }, - { - text: Scratch.translate("back"), - value: "back", - }, - { - text: Scratch.translate("elastic"), - value: "elastic", - }, - { - text: Scratch.translate("bounce"), - value: "bounce", - }, - ], + items: Object.keys(EasingMethods), }, direction: { acceptReporters: true, - items: [ - { - text: Scratch.translate("in"), - value: "in", - }, - { - text: Scratch.translate("out"), - value: "out", - }, - { - text: Scratch.translate("in out"), - value: "in out", - }, - ], + items: ["in", "out", "in out"], }, vars: { acceptReporters: false, // for Scratch parity @@ -453,24 +387,7 @@ }, properties: { acceptReporters: true, - items: [ - { - text: Scratch.translate("x position"), - value: "x position", - }, - { - text: Scratch.translate("y position"), - value: "y position", - }, - { - text: Scratch.translate("direction"), - value: "direction", - }, - { - text: Scratch.translate("size"), - value: "size", - }, - ], + items: ["x position", "y position", "direction", "size"], }, }, }; diff --git a/extensions/Lily/AllMenus.js b/extensions/Lily/AllMenus.js index d51f05ba0c..b124a44ff2 100644 --- a/extensions/Lily/AllMenus.js +++ b/extensions/Lily/AllMenus.js @@ -7,53 +7,28 @@ (function (Scratch) { "use strict"; - let blockXML; + var blockXML; + const blacklist = ["looks_costumenumbername", "extension_wedo_tilt_menu"]; - const blocklist = [ - "looks_costumenumbername", - "extension_wedo_tilt_menu", - - // Unused menu in More Events that won't be translated - "lmsMoreEvents_menu_state", - ]; - - const escapeXML = (text) => - text.replace(/["'&<>]/g, (i) => { - switch (i) { - case "&": - return "&"; - case '"': - return "'"; - case "'": - return """; - case ">": - return ">"; - case "<": - return "<"; - } - return ""; - }); + Scratch.vm.addListener("BLOCKSINFO_UPDATE", refreshMenus); - const refreshMenus = () => { + function refreshMenus() { if (!window.ScratchBlocks) return; Scratch.vm.removeListener("BLOCKSINFO_UPDATE", refreshMenus); let allBlocks = Object.keys(ScratchBlocks.Blocks); allBlocks = allBlocks.filter( - (item) => item.includes("menu") && !blocklist.includes(item) + (item) => item.includes("menu") && !blacklist.includes(item) ); const menuBlocks = allBlocks.map( - (item) => - '' + (item) => '' ); blockXML = menuBlocks.join(""); Scratch.vm.runtime.extensionManager.refreshBlocks(); - }; - - Scratch.vm.addListener("BLOCKSINFO_UPDATE", refreshMenus); + } class AllMenus { constructor() { @@ -65,7 +40,7 @@ getInfo() { return { id: "lmsAllMenus", - name: Scratch.translate("All Menus"), + name: "All Menus", blocks: [ { blockType: Scratch.BlockType.XML, diff --git a/extensions/Lily/Assets.js b/extensions/Lily/Assets.js index 282a910fc8..ef96fc1563 100644 --- a/extensions/Lily/Assets.js +++ b/extensions/Lily/Assets.js @@ -362,14 +362,8 @@ const assetType = this._typeIsBitmap(blob.type) ? runtime.storage.AssetType.ImageBitmap : runtime.storage.AssetType.ImageVector; - - // Bitmap data format is not actually enforced, but setting it to something that isn't in scratch-parser's - // known format list will throw an error when someone tries to load the project. - // (https://github.com/scratchfoundation/scratch-parser/blob/665f05d739a202d565a4af70a201909393d456b2/lib/sb3_definitions.json#L51) const dataType = - blob.type === "image/svg+xml" - ? runtime.storage.DataFormat.SVG - : runtime.storage.DataFormat.PNG; + blob.type === "image/svg+xml" ? "svg" : blob.type.split("/")[1]; const arrayBuffer = await new Promise((resolve, reject) => { const fr = new FileReader(); diff --git a/extensions/Lily/ClonesPlus.js b/extensions/Lily/ClonesPlus.js index ff03493ad0..e3c37f616d 100644 --- a/extensions/Lily/ClonesPlus.js +++ b/extensions/Lily/ClonesPlus.js @@ -48,7 +48,7 @@ getInfo() { return { id: "lmsclonesplus", - name: Scratch.translate("Clones+"), + name: "Clones+", color1: "#FFAB19", color2: "#EC9C13", color3: "#CF8B17", @@ -57,9 +57,7 @@ { opcode: "whenCloneStartsWithVar", blockType: Scratch.BlockType.HAT, - text: Scratch.translate( - "when I start as a clone with [INPUTA] set to [INPUTB]" - ), + text: "when I start as a clone with [INPUTA] set to [INPUTB]", filter: [Scratch.TargetType.SPRITE], arguments: { INPUTA: { @@ -76,9 +74,7 @@ { opcode: "createCloneWithVar", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "create clone with [INPUTA] set to [INPUTB]" - ), + text: "create clone with [INPUTA] set to [INPUTB]", filter: [Scratch.TargetType.SPRITE], arguments: { INPUTA: { @@ -98,9 +94,7 @@ { opcode: "touchingCloneWithVar", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate( - "touching clone with [INPUTA] set to [INPUTB]?" - ), + text: "touching clone with [INPUTA] set to [INPUTB]?", filter: [Scratch.TargetType.SPRITE], arguments: { INPUTA: { @@ -117,7 +111,7 @@ { opcode: "touchingMainSprite", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("touching main sprite?"), + text: "touching main sprite?", filter: [Scratch.TargetType.SPRITE], disableMonitor: true, extensions: ["colours_control"], @@ -128,9 +122,7 @@ { opcode: "setVariableOfClone", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "set variable [INPUTA] to [INPUTB] for clones with [INPUTC] set to [INPUTD]" - ), + text: "set variable [INPUTA] to [INPUTB] for clones with [INPUTC] set to [INPUTD]", filter: [Scratch.TargetType.SPRITE], arguments: { INPUTA: { @@ -155,9 +147,7 @@ { opcode: "getVariableOfClone", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate( - "variable [INPUTA] of clone with [INPUTB] set to [INPUTC]" - ), + text: "variable [INPUTA] of clone with [INPUTB] set to [INPUTC]", filter: [Scratch.TargetType.SPRITE], disableMonitor: true, arguments: { @@ -179,9 +169,7 @@ { opcode: "setVariableOfMainSprite", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "set variable [INPUTA] to [INPUTB] for main sprite" - ), + text: "set variable [INPUTA] to [INPUTB] for main sprite", filter: [Scratch.TargetType.SPRITE], arguments: { INPUTA: { @@ -198,7 +186,7 @@ { opcode: "getVariableOfMainSprite", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("variable [INPUT] of main sprite"), + text: "variable [INPUT] of main sprite", filter: [Scratch.TargetType.SPRITE], disableMonitor: true, arguments: { @@ -215,9 +203,7 @@ { opcode: "cloneExists", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate( - "clone with [INPUTA] set to [INPUTB] exists?" - ), + text: "clone with [INPUTA] set to [INPUTB] exists?", filter: [Scratch.TargetType.SPRITE], arguments: { INPUTA: { @@ -234,14 +220,13 @@ { opcode: "getThingOfClone", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate( - "[INPUTA] of clone with [INPUTB] set to [INPUTC]" - ), + text: "[INPUTA] of clone with [INPUTB] set to [INPUTC]", filter: [Scratch.TargetType.SPRITE], disableMonitor: true, arguments: { INPUTA: { type: Scratch.ArgumentType.STRING, + defaultValue: "x position", menu: "thingOfMenu", }, INPUTB: { @@ -258,12 +243,13 @@ { opcode: "getThingOfMainSprite", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("[INPUT] of main sprite"), + text: "[INPUT] of main sprite", filter: [Scratch.TargetType.SPRITE], disableMonitor: true, arguments: { INPUT: { type: Scratch.ArgumentType.STRING, + defaultValue: "x position", menu: "thingOfMenu", }, }, @@ -275,7 +261,7 @@ { opcode: "stopScriptsInSprite", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("stop scripts in [INPUT]"), + text: "stop scripts in [INPUT]", arguments: { INPUT: { type: Scratch.ArgumentType.STRING, @@ -287,9 +273,7 @@ { opcode: "stopScriptsInClone", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "stop scripts in clones with [INPUTA] set to [INPUTB]" - ), + text: "stop scripts in clones with [INPUTA] set to [INPUTB]", filter: [Scratch.TargetType.SPRITE], arguments: { INPUTA: { @@ -306,7 +290,7 @@ { opcode: "stopScriptsInMainSprite", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("stop scripts in main sprite"), + text: "stop scripts in main sprite", filter: [Scratch.TargetType.SPRITE], extensions: ["colours_control"], }, @@ -316,7 +300,7 @@ { opcode: "deleteClonesInSprite", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("delete clones in [INPUT]"), + text: "delete clones in [INPUT]", arguments: { INPUT: { type: Scratch.ArgumentType.STRING, @@ -328,9 +312,7 @@ { opcode: "deleteCloneWithVar", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "delete clones with [INPUTA] set to [INPUTB]" - ), + text: "delete clones with [INPUTA] set to [INPUTB]", filter: [Scratch.TargetType.SPRITE], arguments: { INPUTA: { @@ -350,7 +332,7 @@ { opcode: "isClone", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("is clone?"), + text: "is clone?", filter: [Scratch.TargetType.SPRITE], disableMonitor: true, extensions: ["colours_control"], @@ -361,13 +343,13 @@ { opcode: "cloneCount", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("clone count"), + text: "clone count", extensions: ["colours_control"], }, { opcode: "spriteCloneCount", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("clone count of [INPUT]"), + text: "clone count of [INPUT]", disableMonitor: true, arguments: { INPUT: { @@ -392,31 +374,31 @@ acceptReporters: false, items: [ { - text: Scratch.translate("x position"), + text: "x position", value: "x position", }, { - text: Scratch.translate("y position"), + text: "y position", value: "y position", }, { - text: Scratch.translate("direction"), + text: "direction", value: "direction", }, { - text: Scratch.translate("costume #"), + text: "costume #", value: "costume num", }, { - text: Scratch.translate("costume name"), + text: "costume name", value: "costume name", }, { - text: Scratch.translate("size"), + text: "size", value: "size", }, { - text: Scratch.translate("volume"), + text: "volume", value: "volume", }, ], @@ -643,20 +625,17 @@ getSprites() { let spriteNames = []; const targets = Scratch.vm.runtime.targets; - const editingTarget = Scratch.vm.runtime.getEditingTarget(); + const myself = Scratch.vm.runtime.getEditingTarget().sprite.name; for (let index = 1; index < targets.length; index++) { - const curTarget = targets[index]; - let display = curTarget.getName(); - if (editingTarget === curTarget) { - display = Scratch.translate({ - default: "myself", - description: "Item in a dropdown that refers to the current sprite", - }); + const curTarget = targets[index].sprite; + let display = curTarget.name; + if (myself === curTarget.name) { + display = "myself"; } if (targets[index].isOriginal) { const jsonOBJ = { text: display, - value: curTarget.getName(), + value: curTarget.name, }; spriteNames.push(jsonOBJ); } diff --git a/extensions/Lily/CommentBlocks.js b/extensions/Lily/CommentBlocks.js index bd478afdfd..ca79522211 100644 --- a/extensions/Lily/CommentBlocks.js +++ b/extensions/Lily/CommentBlocks.js @@ -9,13 +9,9 @@ class CommentBlocks { getInfo() { - const defaultValue = Scratch.translate({ - default: "comment", - description: "Default comment value", - }); return { id: "lmscomments", - name: Scratch.translate("Comment Blocks"), + name: "Comment Blocks", color1: "#e4db8c", color2: "#c6be79", color3: "#a8a167", @@ -28,7 +24,7 @@ arguments: { COMMENT: { type: Scratch.ArgumentType.STRING, - defaultValue: defaultValue, + defaultValue: "comment", }, }, }, @@ -39,7 +35,7 @@ arguments: { COMMENT: { type: Scratch.ArgumentType.STRING, - defaultValue: defaultValue, + defaultValue: "comment", }, }, }, @@ -50,7 +46,7 @@ arguments: { COMMENT: { type: Scratch.ArgumentType.STRING, - defaultValue: defaultValue, + defaultValue: "comment", }, }, }, @@ -62,7 +58,7 @@ arguments: { COMMENT: { type: Scratch.ArgumentType.STRING, - defaultValue: defaultValue, + defaultValue: "comment", }, INPUT: { type: Scratch.ArgumentType.STRING, @@ -77,7 +73,7 @@ arguments: { COMMENT: { type: Scratch.ArgumentType.STRING, - defaultValue: defaultValue, + defaultValue: "comment", }, INPUT: { type: Scratch.ArgumentType.BOOLEAN, diff --git a/extensions/Lily/HackedBlocks.js b/extensions/Lily/HackedBlocks.js index 950bc20b7a..876a04744f 100644 --- a/extensions/Lily/HackedBlocks.js +++ b/extensions/Lily/HackedBlocks.js @@ -12,7 +12,7 @@ getInfo() { return { id: "lmsHackedBlocks", - name: Scratch.translate("Hidden Blocks"), + name: "Hidden Blocks", docsURI: "https://en.scratch-wiki.info/wiki/Hidden_Blocks#Events", blocks: [ // Use the sensing_touchingobjectmenu instead of event_ to also list sprites, since the block supports it diff --git a/extensions/Lily/ListTools.js b/extensions/Lily/ListTools.js index e97c64488a..4eb3e76b3f 100644 --- a/extensions/Lily/ListTools.js +++ b/extensions/Lily/ListTools.js @@ -28,7 +28,7 @@ getInfo() { return { id: "lmsData", - name: Scratch.translate("List Tools"), + name: "List Tools", color1: "#ff661a", color2: "#f2590d", color3: "#e64d00", @@ -36,7 +36,7 @@ { opcode: "deleteItems", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("delete items [NUM1] to [NUM2] of [LIST]"), + text: "delete items [NUM1] to [NUM2] of [LIST]", arguments: { NUM1: { type: Scratch.ArgumentType.NUMBER, @@ -55,7 +55,7 @@ { opcode: "deleteAllOfItem", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("delete all [ITEM] in [LIST]"), + text: "delete all [ITEM] in [LIST]", arguments: { ITEM: { type: Scratch.ArgumentType.STRING, @@ -70,9 +70,7 @@ { opcode: "replaceAllOfItem", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "replace all [ITEM1] with [ITEM2] in [LIST]" - ), + text: "replace all [ITEM1] with [ITEM2] in [LIST]", arguments: { ITEM1: { type: Scratch.ArgumentType.STRING, @@ -91,7 +89,7 @@ { opcode: "repeatList", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("repeat [LIST1] [NUM] times in [LIST2]"), + text: "repeat [LIST1] [NUM] times in [LIST2]", arguments: { LIST1: { type: Scratch.ArgumentType.STRING, @@ -113,7 +111,7 @@ { opcode: "getListJoin", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("list [LIST] joined by [STRING]"), + text: "get list [LIST] joined by [STRING]", disableMonitor: true, arguments: { LIST: { @@ -129,7 +127,7 @@ { opcode: "timesItemAppears", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("# of times [ITEM] appears in [LIST]"), + text: "# of times [ITEM] appears in [LIST]", disableMonitor: true, arguments: { ITEM: { @@ -145,7 +143,7 @@ { opcode: "itemIndex", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("index # [INDEX] of item [ITEM] in [LIST]"), + text: "index # [INDEX] of item [ITEM] in [LIST]", disableMonitor: true, arguments: { INDEX: { @@ -168,7 +166,7 @@ { opcode: "listIsEmpty", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("[LIST] is empty?"), + text: "[LIST] is empty?", disableMonitor: true, arguments: { LIST: { @@ -180,7 +178,7 @@ { opcode: "itemNumExists", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("item [NUM] exists in [LIST]?"), + text: "item [NUM] exists in [LIST]?", disableMonitor: true, arguments: { NUM: { @@ -196,7 +194,7 @@ { opcode: "orderIs", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("order of [LIST] is [ORDER]?"), + text: "order of [LIST] is [ORDER]?", disableMonitor: true, arguments: { LIST: { @@ -215,7 +213,7 @@ { opcode: "orderList", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set order of [LIST] to [ORDER]"), + text: "set order of [LIST] to [ORDER]", disableMonitor: true, arguments: { LIST: { @@ -232,7 +230,7 @@ { opcode: "setListToList", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set items of [LIST1] to [LIST2]"), + text: "set items of [LIST1] to [LIST2]", arguments: { LIST1: { type: Scratch.ArgumentType.STRING, @@ -247,7 +245,7 @@ { opcode: "joinLists", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("concatenate [LIST1] onto [LIST2]"), + text: "concatenate [LIST1] onto [LIST2]", arguments: { LIST1: { type: Scratch.ArgumentType.STRING, @@ -265,7 +263,7 @@ { opcode: "forEachListItem", blockType: Scratch.BlockType.LOOP, - text: Scratch.translate("for each item value [VAR] in [LIST]"), + text: "for each item value [VAR] in [LIST]", hideFromPalette: !runtime.extensionManager.isExtensionLoaded("lmsTempVars2"), arguments: { @@ -282,7 +280,7 @@ { opcode: "forEachListItemNum", blockType: Scratch.BlockType.LOOP, - text: Scratch.translate("for each item # [VAR] in [LIST]"), + text: "for each item # [VAR] in [LIST]", hideFromPalette: !runtime.extensionManager.isExtensionLoaded("lmsTempVars2"), arguments: { @@ -302,7 +300,7 @@ { opcode: "setListArray", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set [LIST] to array [ARRAY]"), + text: "set [LIST] to array [ARRAY]", disableMonitor: true, arguments: { LIST: { @@ -318,7 +316,7 @@ { opcode: "getListArray", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("[LIST] as array"), + text: "[LIST] as array", disableMonitor: true, arguments: { LIST: { @@ -350,19 +348,19 @@ acceptReporters: false, items: [ { - text: Scratch.translate("reversed"), + text: "reversed", value: "reversed", }, { - text: Scratch.translate("ascending"), + text: "ascending", value: "ascending", }, { - text: Scratch.translate("descending"), + text: "descending", value: "descending", }, { - text: Scratch.translate("randomized"), + text: "randomised", value: "randomised", }, ], @@ -371,11 +369,11 @@ acceptReporters: false, items: [ { - text: Scratch.translate("ascending"), + text: "ascending", value: "ascending", }, { - text: Scratch.translate("descending"), + text: "descending", value: "descending", }, ], @@ -384,15 +382,15 @@ acceptReporters: false, items: [ { - text: Scratch.translate("first"), + text: "first", value: "first", }, { - text: Scratch.translate("last"), + text: "last", value: "last", }, { - text: Scratch.translate("random"), + text: "random", value: "random", }, ], diff --git a/extensions/Lily/LooksPlus.js b/extensions/Lily/LooksPlus.js index 2a7bc3bfe5..7061612c6b 100644 --- a/extensions/Lily/LooksPlus.js +++ b/extensions/Lily/LooksPlus.js @@ -33,13 +33,11 @@ return util.runtime.getSpriteTargetByName(nameString); }; - const renderer = Scratch.vm.runtime.renderer; - class LooksPlus { getInfo() { return { id: "lmsLooksPlus", - name: Scratch.translate("Looks+"), + name: "Looks+", color1: "#9966FF", color2: "#855CD6", color3: "#774DCB", @@ -48,7 +46,7 @@ { opcode: "showSprite", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("show [TARGET]"), + text: "show [TARGET]", arguments: { TARGET: { type: Scratch.ArgumentType.STRING, @@ -60,7 +58,7 @@ { opcode: "hideSprite", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("hide [TARGET]"), + text: "hide [TARGET]", arguments: { TARGET: { type: Scratch.ArgumentType.STRING, @@ -72,7 +70,7 @@ { opcode: "spriteVisible", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("[TARGET] visible?"), + text: "[TARGET] visible?", arguments: { TARGET: { type: Scratch.ArgumentType.STRING, @@ -87,7 +85,7 @@ { opcode: "setLayerTo", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set layer # of [TARGET] to [LAYER]"), + text: "set layer # of [TARGET] to [LAYER]", arguments: { TARGET: { type: Scratch.ArgumentType.STRING, @@ -103,7 +101,7 @@ { opcode: "spriteLayerNumber", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("layer # of [TARGET]"), + text: "layer # of [TARGET]", arguments: { TARGET: { type: Scratch.ArgumentType.STRING, @@ -115,7 +113,7 @@ { opcode: "effectValue", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("[EFFECT] effect of [TARGET]"), + text: "[EFFECT] effect of [TARGET]", arguments: { EFFECT: { type: Scratch.ArgumentType.STRING, @@ -135,7 +133,7 @@ { opcode: "targetCostumeNumber", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("# of costumes in [TARGET]"), + text: "# of costumes in [TARGET]", arguments: { TARGET: { type: Scratch.ArgumentType.STRING, @@ -147,7 +145,7 @@ { opcode: "costumeAttribute", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("[ATTRIBUTE] of [COSTUME]"), + text: "[ATTRIBUTE] of [COSTUME]", arguments: { ATTRIBUTE: { type: Scratch.ArgumentType.STRING, @@ -165,7 +163,7 @@ { opcode: "snapshotStage", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("snapshot stage"), + text: "snapshot stage", disableMonitor: true, extensions: ["colours_looks"], }, @@ -175,7 +173,7 @@ { opcode: "replaceCostumeContent", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set [TYPE] for [COSTUME] to [CONTENT]"), + text: "set [TYPE] for [COSTUME] to [CONTENT]", arguments: { TYPE: { type: Scratch.ArgumentType.STRING, @@ -195,7 +193,7 @@ { opcode: "restoreCostumeContent", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("restore content for [COSTUME]"), + text: "restore content for [COSTUME]", arguments: { COSTUME: { type: Scratch.ArgumentType.COSTUME, @@ -206,9 +204,7 @@ { opcode: "costumeContent", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate( - "[CONTENT] of costume # [COSTUME] of [TARGET]" - ), + text: "[CONTENT] of costume # [COSTUME] of [TARGET]", arguments: { CONTENT: { type: Scratch.ArgumentType.STRING, @@ -232,7 +228,7 @@ { opcode: "replaceColors", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("replace [COLOR1] with [COLOR2] in [SVG]"), + text: "replace [COLOR1] with [COLOR2] in [SVG]", arguments: { COLOR1: { type: Scratch.ArgumentType.COLOR, @@ -252,7 +248,7 @@ { opcode: "colorHex", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("hex of [COLOR]"), + text: "hex of [COLOR]", arguments: { COLOR: { type: Scratch.ArgumentType.COLOR, @@ -268,31 +264,31 @@ acceptReporters: false, items: [ { - text: Scratch.translate("color"), + text: "color", value: "color", }, { - text: Scratch.translate("fisheye"), + text: "fisheye", value: "fisheye", }, { - text: Scratch.translate("whirl"), + text: "whirl", value: "whirl", }, { - text: Scratch.translate("pixelate"), + text: "pixelate", value: "pixelate", }, { - text: Scratch.translate("mosaic"), + text: "mosaic", value: "mosaic", }, { - text: Scratch.translate("brightness"), + text: "brightness", value: "brightness", }, { - text: Scratch.translate("ghost"), + text: "ghost", value: "ghost", }, ], @@ -301,23 +297,23 @@ acceptReporters: false, items: [ { - text: Scratch.translate("width"), + text: "width", value: "width", }, { - text: Scratch.translate("height"), + text: "height", value: "height", }, { - text: Scratch.translate("format"), + text: "format", value: "format", }, { - text: Scratch.translate("rotation center x"), + text: "rotation center x", value: "rotationCenterX", }, { - text: Scratch.translate("rotation center y"), + text: "rotation center y", value: "rotationCenterY", }, ], @@ -326,11 +322,11 @@ acceptReporters: false, items: [ { - text: Scratch.translate("content"), + text: "content", value: "content", }, { - text: Scratch.translate("dataURI"), + text: "dataURI", value: "dataURI", }, ], @@ -382,7 +378,7 @@ const drawableID = target.drawableID; const layerOrder = target.getLayerOrder(); const newLayer = args.LAYER - layerOrder; - renderer.setDrawableOrder(drawableID, newLayer, "sprite", true); + target.renderer.setDrawableOrder(drawableID, newLayer, "sprite", true); } spriteLayerNumber(args, util) { @@ -444,7 +440,7 @@ snapshotStage(args, util) { return new Promise((resolve) => { - renderer.requestSnapshot((uri) => { + Scratch.vm.runtime.renderer.requestSnapshot((uri) => { resolve(uri); }); }); @@ -469,18 +465,15 @@ const contentType = args.TYPE; const content = args.CONTENT; if (contentType === "SVG") { - try { - renderer.updateSVGSkin( - costume.skinId, - Scratch.Cast.toString(content) - ); - renderer._allSkins[costume.skinId].differsFromAsset = true; - } catch (e) { - console.error(e); - } + Scratch.vm.runtime.renderer.updateSVGSkin( + costume.skinId, + Scratch.Cast.toString(content) + ); } else { console.error("Options other than SVG are currently unavailable"); + return; } + Scratch.vm.emitTargetsUpdate(); } restoreCostumeContent(args, util) { @@ -495,30 +488,21 @@ return; } - // This is here to ensure no changes are made to bitmap costumes, as changes are irreversible - // Check will be removed when it's possible to edit bitmap skins + //This is here to ensure no changes are made to bitmap costumes, as changes are irreversible + //Check will be removed when it's possible to edit bitmap skins const format = costume.asset.assetType.runtimeFormat; if (format !== "svg") { console.error("Costume is not vector"); return; } - if (!renderer._allSkins[costume.skinId].differsFromAsset) { - return; - } - - try { - const content = costume.asset.decodeText(); - const rotationCenterX = costume.rotationCenterX; - const rotationCenterY = costume.rotationCenterY; - renderer.updateSVGSkin(costume.skinId, content, [ - rotationCenterX, - rotationCenterY, - ]); - renderer._allSkins[costume.skinId].differsFromAsset = false; - } catch (e) { - console.error(e); - } + const content = costume.asset.decodeText(); + const rotationCenterX = costume.rotationCenterX; + const rotationCenterY = costume.rotationCenterY; + util.target.renderer.updateSVGSkin(costume.skinId, content, [ + rotationCenterX, + rotationCenterY, + ]); } costumeContent(args, util) { @@ -583,12 +567,12 @@ getSprites() { const spriteNames = []; const targets = Scratch.vm.runtime.targets; - const editingTarget = Scratch.vm.runtime.getEditingTarget(); + const myself = Scratch.vm.runtime.getEditingTarget().getName(); for (let index = 1; index < targets.length; index++) { const target = targets[index]; if (target.isOriginal) { const targetName = target.getName(); - if (target === editingTarget) { + if (targetName === myself) { spriteNames.unshift({ text: "this sprite", value: targetName, diff --git a/extensions/Lily/McUtils.js b/extensions/Lily/McUtils.js index f85ad2f14f..7241c5a1e6 100644 --- a/extensions/Lily/McUtils.js +++ b/extensions/Lily/McUtils.js @@ -23,11 +23,7 @@ { opcode: "managerReporter", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate({ - default: "if [INPUTA] is manager then [INPUTB] else [INPUTC]", - description: - "This is a joke block equivalent to 'if [INPUTA] then [INPUTB] else [INPUTC]", - }), + text: "if [INPUTA] is manager then [INPUTB] else [INPUTC]", arguments: { INPUTA: { type: Scratch.ArgumentType.BOOLEAN, @@ -43,11 +39,7 @@ { opcode: "icecreammachine", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate({ - default: "is ice cream machine [INPUT]", - description: - "This is a joke block. [INPUT] can be 'working' (reports false) and 'broken' (reports true) because the machine is always broken.", - }), + text: "is ice cream machine [INPUT]", arguments: { INPUT: { type: Scratch.ArgumentType.STRING, @@ -58,11 +50,7 @@ { opcode: "talkToManager", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate({ - default: "talk to manager [INPUT]", - description: - "This is a joke block that just reports whatever you put into it.", - }), + text: "talk to manager [INPUT]", arguments: { INPUT: { type: Scratch.ArgumentType.STRING, @@ -72,11 +60,7 @@ { opcode: "placeOrder", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate({ - default: "place order [INPUT]", - description: - "This is a joke block that just reports whatever yout put into it, except if it contains 'ice cream', then false because the machine is always broken.", - }), + text: "place order [INPUT]", arguments: { INPUT: { type: Scratch.ArgumentType.STRING, @@ -96,19 +80,11 @@ acceptReporters: true, items: [ { - text: Scratch.translate({ - default: "working", - description: - "Used in context 'is ice cream machine [working]?', a joke block", - }), + text: "working", value: "working", }, { - text: Scratch.translate({ - default: "broken", - description: - "Used in context 'is ice cream machine [broken]?', a joke block", - }), + text: "broken", value: "broken", }, ], diff --git a/extensions/Lily/MoreEvents.js b/extensions/Lily/MoreEvents.js index b215802af8..8c768fd78c 100644 --- a/extensions/Lily/MoreEvents.js +++ b/extensions/Lily/MoreEvents.js @@ -210,7 +210,7 @@ getInfo() { return { id: "lmsMoreEvents", - name: Scratch.translate("More Events"), + name: "More Events", color1: "#FFBF00", color2: "#E6AC00", color3: "#CC9900", @@ -218,7 +218,7 @@ { opcode: "whenStopClicked", blockType: Scratch.BlockType.EVENT, - text: Scratch.translate("when [STOP] clicked"), + text: "when [STOP] clicked", isEdgeActivated: false, arguments: { STOP: { @@ -231,7 +231,7 @@ { opcode: "forever", blockType: Scratch.BlockType.EVENT, - text: Scratch.translate("forever"), + text: "forever", isEdgeActivated: false, extensions: ["colours_event"], }, @@ -241,7 +241,7 @@ { opcode: "whenTrueFalse", blockType: Scratch.BlockType.HAT, - text: Scratch.translate("when [CONDITION] becomes [STATE]"), + text: "when [CONDITION] becomes [STATE]", isEdgeActivated: true, arguments: { CONDITION: { @@ -257,7 +257,7 @@ { opcode: "whileTrueFalse", blockType: Scratch.BlockType.HAT, - text: Scratch.translate("while [CONDITION] is [STATE]"), + text: "while [CONDITION] is [STATE]", isEdgeActivated: false, arguments: { CONDITION: { @@ -276,7 +276,7 @@ { opcode: "whenValueChanged", blockType: Scratch.BlockType.HAT, - text: Scratch.translate("when [INPUT] is changed"), + text: "when [INPUT] is changed", isEdgeActivated: false, arguments: { INPUT: { @@ -291,7 +291,7 @@ { opcode: "everyDuration", blockType: Scratch.BlockType.HAT, - text: Scratch.translate("every [DURATION] frames"), + text: "every [DURATION] frames", isEdgeActivated: false, arguments: { DURATION: { @@ -307,7 +307,7 @@ { opcode: "whenKeyAction", blockType: Scratch.BlockType.HAT, - text: Scratch.translate("when [KEY_OPTION] key [ACTION]"), + text: "when [KEY_OPTION] key [ACTION]", isEdgeActivated: true, arguments: { KEY_OPTION: { @@ -325,7 +325,7 @@ { opcode: "whileKeyPressed", blockType: Scratch.BlockType.HAT, - text: Scratch.translate("while [KEY_OPTION] key pressed"), + text: "while [KEY_OPTION] key pressed", isEdgeActivated: false, arguments: { KEY_OPTION: { @@ -342,7 +342,7 @@ { opcode: "broadcastToTarget", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("broadcast [BROADCAST_OPTION] to [TARGET]"), + text: "broadcast [BROADCAST_OPTION] to [TARGET]", arguments: { BROADCAST_OPTION: { type: null, @@ -358,9 +358,7 @@ { opcode: "broadcastToTargetAndWait", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "broadcast [BROADCAST_OPTION] to [TARGET] and wait" - ), + text: "broadcast [BROADCAST_OPTION] to [TARGET] and wait", arguments: { BROADCAST_OPTION: { type: null, @@ -379,9 +377,7 @@ { opcode: "broadcastData", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "broadcast [BROADCAST_OPTION] with data [DATA]" - ), + text: "broadcast [BROADCAST_OPTION] with data [DATA]", arguments: { BROADCAST_OPTION: { type: null, @@ -396,9 +392,7 @@ { opcode: "broadcastDataAndWait", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "broadcast [BROADCAST_OPTION] with data [DATA] and wait" - ), + text: "broadcast [BROADCAST_OPTION] with data [DATA] and wait", arguments: { BROADCAST_OPTION: { type: null, @@ -417,7 +411,7 @@ { opcode: "receivedData", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("received data"), + text: "received data", disableMonitor: true, allowDropAnywhere: true, extensions: ["colours_event"], @@ -428,9 +422,7 @@ { opcode: "broadcastDataToTarget", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "broadcast [BROADCAST_OPTION] to [TARGET] with data [DATA]" - ), + text: "broadcast [BROADCAST_OPTION] to [TARGET] with data [DATA]", func: "broadcastToTarget", arguments: { BROADCAST_OPTION: { @@ -450,9 +442,7 @@ { opcode: "broadcastDataToTargetAndWait", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "broadcast [BROADCAST_OPTION] to [TARGET] with data [DATA] and wait" - ), + text: "broadcast [BROADCAST_OPTION] to [TARGET] with data [DATA] and wait", func: "broadcastToTargetAndWait", arguments: { BROADCAST_OPTION: { @@ -477,7 +467,7 @@ { blockType: Scratch.BlockType.EVENT, opcode: "beforeSave", - text: Scratch.translate("before project saves"), + text: "before project saves", shouldRestartExistingThreads: true, isEdgeActivated: false, extensions: ["colours_event"], @@ -485,7 +475,7 @@ { blockType: Scratch.BlockType.EVENT, opcode: "afterSave", - text: Scratch.translate("after project saves"), + text: "after project saves", shouldRestartExistingThreads: true, isEdgeActivated: false, extensions: ["colours_event"], @@ -504,39 +494,15 @@ // Attributes have acceptReporters: false action: { acceptReporters: false, - items: [ - { - text: Scratch.translate("hit"), - value: "hit", - }, - { - text: Scratch.translate("released"), - value: "released", - }, - ], + items: ["hit", "released"], }, boolean: { acceptReporters: false, - items: [ - { - text: Scratch.translate("true"), - value: "true", - }, - { - text: Scratch.translate("false"), - value: "false", - }, - ], + items: ["true", "false"], }, - // This menu is unused, however we can't remove it as that could break projects - // that use the menu through the All Menus extension. state: { acceptReporters: false, - items: [ - // Unused, so don't bother translating - "enabled", - "disabled", - ], + items: ["enabled", "disabled"], }, }, }; diff --git a/extensions/Lily/MoreTimers.js b/extensions/Lily/MoreTimers.js index cb0d071737..e57e819fe4 100644 --- a/extensions/Lily/MoreTimers.js +++ b/extensions/Lily/MoreTimers.js @@ -40,7 +40,7 @@ getInfo() { return { id: "lmsTimers", - name: Scratch.translate("More Timers"), + name: "More Timers", color1: "#5cb1d6", color2: "#428faf", color3: "#3281a3", @@ -49,7 +49,7 @@ opcode: "whenTimerOp", blockType: Scratch.BlockType.HAT, extensions: ["colours_sensing"], - text: Scratch.translate("when timer [TIMER] [OP] [NUM]"), + text: "when timer [TIMER] [OP] [NUM]", arguments: { TIMER: { type: Scratch.ArgumentType.STRING, @@ -72,7 +72,7 @@ opcode: "startResetTimer", blockType: Scratch.BlockType.COMMAND, extensions: ["colours_sensing"], - text: Scratch.translate("start/reset timer [TIMER]"), + text: "start/reset timer [TIMER]", arguments: { TIMER: { type: Scratch.ArgumentType.STRING, @@ -84,7 +84,7 @@ opcode: "valueOfTimer", blockType: Scratch.BlockType.REPORTER, extensions: ["colours_sensing"], - text: Scratch.translate("timer [TIMER]"), + text: "timer [TIMER]", arguments: { TIMER: { type: Scratch.ArgumentType.STRING, @@ -99,7 +99,7 @@ opcode: "pauseTimer", blockType: Scratch.BlockType.COMMAND, extensions: ["colours_sensing"], - text: Scratch.translate("pause timer [TIMER]"), + text: "pause timer [TIMER]", arguments: { TIMER: { type: Scratch.ArgumentType.STRING, @@ -111,7 +111,7 @@ opcode: "resumeTimer", blockType: Scratch.BlockType.COMMAND, extensions: ["colours_sensing"], - text: Scratch.translate("resume timer [TIMER]"), + text: "resume timer [TIMER]", arguments: { TIMER: { type: Scratch.ArgumentType.STRING, @@ -126,7 +126,7 @@ opcode: "setTimer", blockType: Scratch.BlockType.COMMAND, extensions: ["colours_sensing"], - text: Scratch.translate("set timer [TIMER] to [NUM]"), + text: "set timer [TIMER] to [NUM]", arguments: { TIMER: { type: Scratch.ArgumentType.STRING, @@ -142,7 +142,7 @@ opcode: "changeTimer", blockType: Scratch.BlockType.COMMAND, extensions: ["colours_sensing"], - text: Scratch.translate("change timer [TIMER] by [NUM]"), + text: "change timer [TIMER] by [NUM]", arguments: { TIMER: { type: Scratch.ArgumentType.STRING, @@ -161,7 +161,7 @@ opcode: "removeTimer", blockType: Scratch.BlockType.COMMAND, extensions: ["colours_sensing"], - text: Scratch.translate("remove timer [TIMER]"), + text: "remove timer [TIMER]", arguments: { TIMER: { type: Scratch.ArgumentType.STRING, @@ -173,13 +173,13 @@ opcode: "removeTimers", blockType: Scratch.BlockType.COMMAND, extensions: ["colours_sensing"], - text: Scratch.translate("remove all timers"), + text: "remove all timers", }, { opcode: "timerExists", blockType: Scratch.BlockType.BOOLEAN, extensions: ["colours_sensing"], - text: Scratch.translate("timer [TIMER] exists?"), + text: "timer [TIMER] exists?", arguments: { TIMER: { type: Scratch.ArgumentType.STRING, @@ -191,7 +191,7 @@ opcode: "listExistingTimers", blockType: Scratch.BlockType.REPORTER, extensions: ["colours_sensing"], - text: Scratch.translate("list existing timers"), + text: "list existing timers", disableMonitor: false, }, ], diff --git a/extensions/Lily/Skins.js b/extensions/Lily/Skins.js index 601663e4b3..9eba2017e1 100644 --- a/extensions/Lily/Skins.js +++ b/extensions/Lily/Skins.js @@ -40,7 +40,7 @@ const renderer = runtime.renderer; const Cast = Scratch.Cast; - var createdSkins = {}; + var createdSkins = []; class Skins { constructor() { @@ -56,7 +56,7 @@ getInfo() { return { id: "lmsSkins", - name: Scratch.translate("Skins"), + name: "Skins", color1: "#6b56ff", color2: "#604de6", color3: "#5645cc", @@ -65,7 +65,7 @@ { opcode: "registerSVGSkin", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("create SVG skin [SVG] as [NAME]"), + text: "create SVG skin [SVG] as [NAME]", arguments: { SVG: { type: Scratch.ArgumentType.STRING, @@ -83,7 +83,7 @@ { opcode: "registerCostumeSkin", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("load skin from [COSTUME] as [NAME]"), + text: "load skin from [COSTUME] as [NAME]", arguments: { COSTUME: { type: Scratch.ArgumentType.COSTUME, @@ -97,7 +97,7 @@ { opcode: "registerURLSkin", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("load skin from URL [URL] as [NAME]"), + text: "load skin from URL [URL] as [NAME]", arguments: { URL: { type: Scratch.ArgumentType.STRING, @@ -112,7 +112,7 @@ { opcode: "getSkinLoaded", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("skin [NAME] is loaded?"), + text: "skin [NAME] is loaded?", arguments: { NAME: { type: Scratch.ArgumentType.STRING, @@ -126,7 +126,7 @@ { opcode: "setSkin", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set skin of [TARGET] to [NAME]"), + text: "set skin of [TARGET] to [NAME]", arguments: { TARGET: { type: Scratch.ArgumentType.STRING, @@ -141,7 +141,7 @@ { opcode: "restoreSkin", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("restore skin of [TARGET]"), + text: "restore skin of [TARGET]", arguments: { TARGET: { type: Scratch.ArgumentType.STRING, @@ -152,7 +152,7 @@ { opcode: "restoreTargets", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("restore targets with skin [NAME]"), + text: "restore targets with skin [NAME]", arguments: { NAME: { type: Scratch.ArgumentType.STRING, @@ -166,7 +166,7 @@ { opcode: "getCurrentSkin", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("current skin of [TARGET]"), + text: "current skin of [TARGET]", arguments: { TARGET: { type: Scratch.ArgumentType.STRING, @@ -177,7 +177,7 @@ { opcode: "getSkinAttribute", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("[ATTRIBUTE] of skin [NAME]"), + text: "[ATTRIBUTE] of skin [NAME]", arguments: { ATTRIBUTE: { type: Scratch.ArgumentType.STRING, @@ -195,7 +195,7 @@ { opcode: "deleteSkin", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("delete skin [NAME]"), + text: "delete skin [NAME]", arguments: { NAME: { type: Scratch.ArgumentType.STRING, @@ -206,7 +206,7 @@ { opcode: "deleteAllSkins", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("delete all skins"), + text: "delete all skins", }, ], menus: { @@ -216,16 +216,7 @@ }, skinAttributes: { acceptReporters: true, - items: [ - { - text: Scratch.translate("width"), - value: "width", - }, - { - text: Scratch.translate("height"), - value: "height", - }, - ], + items: ["width", "height"], }, }, }; @@ -371,9 +362,9 @@ deleteAllSkins() { this._refreshTargets(); - for (const skinName in createdSkins) - renderer.destroySkin(createdSkins[skinName]); - createdSkins = {}; + for (let i = 0; i < createdSkins.length; i++) + renderer.destroySkin(createdSkins[i]); + createdSkins = []; } restoreTargets(args) { diff --git a/extensions/Lily/SoundExpanded.js b/extensions/Lily/SoundExpanded.js index 00e8c32548..821dffc40b 100644 --- a/extensions/Lily/SoundExpanded.js +++ b/extensions/Lily/SoundExpanded.js @@ -18,12 +18,12 @@ color1: "#CF63CF", color2: "#C94FC9", color3: "#BD42BD", - name: Scratch.translate("Sound Expanded"), + name: "Sound Expanded", blocks: [ { opcode: "startLooping", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("start looping [SOUND]"), + text: "start looping [SOUND]", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -34,9 +34,7 @@ { opcode: "startLoopingBegin", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "start looping [SOUND] loop start [START] seconds" - ), + text: "start looping [SOUND] loop start [START] seconds", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -51,9 +49,7 @@ { opcode: "startLoopingBeginEnd", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "start looping [SOUND] loop region [START] to [END] seconds" - ), + text: "start looping [SOUND] loop region [START] to [END] seconds", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -72,7 +68,7 @@ { opcode: "stopLooping", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("end looping [SOUND]"), + text: "end looping [SOUND]", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -83,7 +79,7 @@ { opcode: "isLooping", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("[SOUND] is looping?"), + text: "[SOUND] is looping?", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -97,9 +93,7 @@ { opcode: "playSoundAtAndWait", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "play sound [SOUND] from [START] seconds until done" - ), + text: "play sound [SOUND] from [START] seconds until done", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -114,7 +108,7 @@ { opcode: "playSoundAt", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("start sound [SOUND] from [START] seconds"), + text: "start sound [SOUND] from [START] seconds", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -129,9 +123,7 @@ { opcode: "playSoundToAndWait", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "play sound [SOUND] from [START] to [END] seconds until done" - ), + text: "play sound [SOUND] from [START] to [END] seconds until done", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -150,9 +142,7 @@ { opcode: "playSoundTo", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate( - "start sound [SOUND] from [START] to [END] seconds" - ), + text: "start sound [SOUND] from [START] to [END] seconds", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -171,7 +161,7 @@ { opcode: "stopSound", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("stop sound [SOUND]"), + text: "stop sound [SOUND]", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -182,7 +172,7 @@ { opcode: "pauseSounds", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("pause all sounds"), + text: "pause all sounds", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -193,7 +183,7 @@ { opcode: "resumeSounds", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("resume all sounds"), + text: "resume all sounds", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -207,7 +197,7 @@ { opcode: "isSoundPlaying", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("sound [SOUND] is playing?"), + text: "sound [SOUND] is playing?", arguments: { SOUND: { type: Scratch.ArgumentType.SOUND, @@ -218,7 +208,7 @@ { opcode: "attributeOfSound", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("[ATTRIBUTE] of [SOUND]"), + text: "[ATTRIBUTE] of [SOUND]", arguments: { ATTRIBUTE: { type: Scratch.ArgumentType.STRING, @@ -233,7 +223,7 @@ { opcode: "getSoundEffect", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("effect [EFFECT] of [TARGET]"), + text: "[EFFECT] of [TARGET]", arguments: { EFFECT: { type: Scratch.ArgumentType.STRING, @@ -250,7 +240,7 @@ { opcode: "setProjectVolume", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set project volume to [VALUE]%"), + text: "set project volume to [VALUE]%", arguments: { VALUE: { type: Scratch.ArgumentType.NUMBER, @@ -262,7 +252,7 @@ { opcode: "changeProjectVolume", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("change project volume by [VALUE]"), + text: "change project volume by [VALUE]", arguments: { VALUE: { type: Scratch.ArgumentType.NUMBER, @@ -274,44 +264,18 @@ { opcode: "getProjectVolume", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("project volume"), + text: "project volume", extensions: ["colours_sounds"], }, ], menus: { attribute: { acceptReporters: false, - items: [ - { - text: Scratch.translate("length"), - value: "length", - }, - { - text: Scratch.translate("channels"), - value: "channels", - }, - { - text: Scratch.translate("sample rate"), - value: "sample rate", - }, - { - text: Scratch.translate("dataURI"), - value: "dataURI", - }, - ], + items: ["length", "channels", "sample rate", "dataURI"], }, effect: { acceptReporters: false, - items: [ - { - text: Scratch.translate("pitch"), - value: "pitch", - }, - { - text: Scratch.translate("pan"), - value: "pan", - }, - ], + items: ["pitch", "pan"], }, targets: { acceptReporters: true, @@ -323,8 +287,7 @@ _startLooping(util, sound, loopStart, loopEnd) { const index = this._getSoundIndex(sound, util); - if (index < 0) return; - + if (index < 0) return 0; const target = util.target; const sprite = util.target.sprite; @@ -337,12 +300,9 @@ } if (!soundPlayer.outputNode) return; - soundPlayer.outputNode.loop = true; soundPlayer.outputNode.loopStart = loopStart; - // If loopEnd is the default of 0, then loopStart is ignored - soundPlayer.outputNode.loopEnd = - loopEnd || soundPlayer.outputNode.buffer.duration; + soundPlayer.outputNode.loopEnd = loopEnd; } startLooping(args, util) { @@ -569,7 +529,7 @@ } setProjectVolume(args) { - const value = Scratch.Cast.toNumber(args.VALUE) / 100; + const value = Scratch.Cast.toNumber(args.VALUE); const newVolume = Scratch.Cast.toNumber(Math.max(Math.min(value, 1), 0)); runtime.audioEngine.inputNode.gain.value = newVolume; } diff --git a/extensions/Lily/TempVariables.js b/extensions/Lily/TempVariables.js index 984a522bfa..a64d63d8d4 100644 --- a/extensions/Lily/TempVariables.js +++ b/extensions/Lily/TempVariables.js @@ -10,7 +10,7 @@ getInfo() { return { id: "lmstempvars", - name: Scratch.translate("Temporary Variables"), + name: "Temporary Variables", color1: "#FF791A", color2: "#E15D00", menuIconURI: menuIconURI, @@ -18,7 +18,7 @@ { opcode: "setVariableTo", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set variable [INPUTA] to [INPUTB]"), + text: "set variable [INPUTA] to [INPUTB]", arguments: { INPUTA: { type: Scratch.ArgumentType.STRING, @@ -33,7 +33,7 @@ { opcode: "changeVariableBy", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("change variable [INPUTA] by [INPUTB]"), + text: "change variable [INPUTA] by [INPUTB]", arguments: { INPUTA: { type: Scratch.ArgumentType.STRING, @@ -48,7 +48,7 @@ { opcode: "getVariable", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("variable [INPUT]"), + text: "variable [INPUT]", disableMonitor: true, arguments: { INPUT: { @@ -63,7 +63,7 @@ { opcode: "deleteVariable", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("delete variable [INPUT]"), + text: "delete variable [INPUT]", arguments: { INPUT: { type: Scratch.ArgumentType.STRING, @@ -74,12 +74,12 @@ { opcode: "deleteAllVariables", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("delete all variables"), + text: "delete all variables", }, { opcode: "listVariables", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("list active variables"), + text: "list active variables", disableMonitor: true, }, ], diff --git a/extensions/Lily/TempVariables2.js b/extensions/Lily/TempVariables2.js index 544f09bcf3..0d7b123b26 100644 --- a/extensions/Lily/TempVariables2.js +++ b/extensions/Lily/TempVariables2.js @@ -35,16 +35,16 @@ getInfo() { return { id: "lmsTempVars2", - name: Scratch.translate("Temporary Variables"), + name: "Temporary Variables", color1: "#FF791A", color2: "#E15D00", blocks: [ - label(Scratch.translate("Thread Variables"), false), + label("Thread Variables", false), { opcode: "setThreadVariable", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set thread var [VAR] to [STRING]"), + text: "set thread var [VAR] to [STRING]", arguments: { VAR: { type: Scratch.ArgumentType.STRING, @@ -59,7 +59,7 @@ { opcode: "changeThreadVariable", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("change thread var [VAR] by [NUM]"), + text: "change thread var [VAR] by [NUM]", arguments: { VAR: { type: Scratch.ArgumentType.STRING, @@ -77,7 +77,7 @@ { opcode: "getThreadVariable", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("thread var [VAR]"), + text: "thread var [VAR]", disableMonitor: true, allowDropAnywhere: true, arguments: { @@ -90,7 +90,7 @@ { opcode: "threadVariableExists", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("thread var [VAR] exists?"), + text: "thread var [VAR] exists?", arguments: { VAR: { type: Scratch.ArgumentType.STRING, @@ -104,7 +104,7 @@ { opcode: "forEachThreadVariable", blockType: Scratch.BlockType.LOOP, - text: Scratch.translate("for [VAR] in [NUM]"), + text: "for [VAR] in [NUM]", arguments: { VAR: { type: Scratch.ArgumentType.STRING, @@ -119,18 +119,18 @@ { opcode: "listThreadVariables", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("active thread variables"), + text: "active thread variables", disableMonitor: true, }, "---", - label(Scratch.translate("Runtime Variables"), false), + label("Runtime Variables", false), { opcode: "setRuntimeVariable", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("set runtime var [VAR] to [STRING]"), + text: "set runtime var [VAR] to [STRING]", arguments: { VAR: { type: Scratch.ArgumentType.STRING, @@ -145,7 +145,7 @@ { opcode: "changeRuntimeVariable", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("change runtime var [VAR] by [NUM]"), + text: "change runtime var [VAR] by [NUM]", arguments: { VAR: { type: Scratch.ArgumentType.STRING, @@ -163,7 +163,7 @@ { opcode: "getRuntimeVariable", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("runtime var [VAR]"), + text: "runtime var [VAR]", disableMonitor: true, allowDropAnywhere: true, arguments: { @@ -176,7 +176,7 @@ { opcode: "runtimeVariableExists", blockType: Scratch.BlockType.BOOLEAN, - text: Scratch.translate("runtime var [VAR] exists?"), + text: "runtime var [VAR] exists?", arguments: { VAR: { type: Scratch.ArgumentType.STRING, @@ -190,7 +190,7 @@ { opcode: "deleteRuntimeVariable", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("delete runtime var [VAR]"), + text: "delete runtime var [VAR]", arguments: { VAR: { type: Scratch.ArgumentType.STRING, @@ -201,12 +201,12 @@ { opcode: "deleteAllRuntimeVariables", blockType: Scratch.BlockType.COMMAND, - text: Scratch.translate("delete all runtime variables"), + text: "delete all runtime variables", }, { opcode: "listRuntimeVariables", blockType: Scratch.BlockType.REPORTER, - text: Scratch.translate("active runtime variables"), + text: "active runtime variables", }, ], }; diff --git a/extensions/Lily/Video.js b/extensions/Lily/Video.js index 879625c06a..e6855aad4d 100644 --- a/extensions/Lily/Video.js +++ b/extensions/Lily/Video.js @@ -2,7 +2,6 @@ // ID: lmsVideo // Description: Play videos from URLs. // By: LilyMakesThings -// By: SharkPool // License: MIT AND LGPL-3.0 // Attribution is not required, but greatly appreciated. @@ -15,21 +14,6 @@ const renderer = vm.renderer; const Cast = Scratch.Cast; - // In some versions of Chrome, it seems that trying to render a