Enhance Scratch UI with custom block colors, themes, and more.
// ==UserScript==
// @name Enhanced Scratch UI and Block Editor
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Enhance Scratch UI with custom block colors, themes, and more.
// @match https://scratch.mit.edu/projects/*
// @match https://scratch.mit.edu/editor/*
// @match https://scratch.mit.edu/ideas*
// @grant GM_addStyle
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
// Utility function to add global styles
function addGlobalStyle(css) {
const style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
document.head.appendChild(style);
}
// Add global styles for the GUI
addGlobalStyle(`
body {
font-family: 'Comic Sans MS', cursive, sans-serif;
}
#scratch-custom-gui {
position: fixed;
top: 10px;
right: 10px;
background-color: #fef9e9;
border: 2px solid #d1a3a4;
padding: 15px;
z-index: 1000;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
font-family: 'Comic Sans MS', cursive, sans-serif;
color: #333;
display: none;
}
#scratch-custom-gui h2 {
font-size: 24px;
border-bottom: 2px dashed #d1a3a4;
padding-bottom: 10px;
margin-bottom: 10px;
}
#scratch-custom-gui button {
margin: 5px;
padding: 8px 15px;
border: 2px solid #d1a3a4;
border-radius: 8px;
background-color: #f8d5d5;
color: #333;
cursor: pointer;
font-family: 'Comic Sans MS', cursive, sans-serif;
font-size: 14px;
}
#scratch-custom-gui button:hover {
background-color: #e8b1b4;
}
#scratch-custom-gui input[type="color"],
#scratch-custom-gui input[type="text"],
#scratch-custom-gui select {
border: 2px solid #d1a3a4;
border-radius: 8px;
padding: 5px;
font-family: 'Comic Sans MS', cursive, sans-serif;
font-size: 14px;
}
#scratch-custom-gui #gui-content {
margin-top: 15px;
}
#scratch-custom-gui #modifiers-list div {
margin: 5px 0;
padding: 5px;
border: 1px dashed #d1a3a4;
border-radius: 8px;
background-color: #fbe8e8;
}
#theme-styles {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
`);
// Create and open GUI
function createAndOpenGUI() {
const gui = document.createElement('div');
gui.id = 'scratch-custom-gui';
gui.innerHTML = `
<h2>Custom Scratch GUI</h2>
<button id="open-block-color-changer">Block Color Changer</button>
<button id="open-block-editor">Block Editor</button>
<button id="open-theme-changer">Theme Changer</button>
<button id="open-modifiers">Modifiers</button>
<button id="close-gui">Close</button>
<div id="gui-content"></div>
`;
document.body.appendChild(gui);
// Event listeners for buttons
document.getElementById('open-block-color-changer').addEventListener('click', openBlockColorChanger);
document.getElementById('open-block-editor').addEventListener('click', openBlockEditor);
document.getElementById('open-theme-changer').addEventListener('click', openThemeChanger);
document.getElementById('open-modifiers').addEventListener('click', openModifiers);
document.getElementById('close-gui').addEventListener('click', closeGUI);
// Open GUI initially
gui.style.display = 'block';
}
// Function to open block color changer
function openBlockColorChanger() {
document.getElementById('gui-content').innerHTML = `
<h3>Block Color Changer</h3>
<label for="block-select-color">Select Block:</label>
<select id="block-select-color">
<!-- Populate with block options dynamically -->
</select>
<br/><br/>
<label for="block-new-color">New Block Color:</label>
<input type="color" id="block-new-color" />
<br/><br/>
<label for="block-inside-color">Inside Color:</label>
<input type="color" id="block-inside-color" />
<br/><br/>
<button onclick="changeBlockColor()">Change Color</button>
`;
populateBlockOptions(); // Populate block options dynamically
}
// Function to open block editor
function openBlockEditor() {
document.getElementById('gui-content').innerHTML = `
<h3>Block Editor</h3>
<label for="block-name">Block Name:</label>
<input type="text" id="block-name" />
<br/><br/>
<label for="block-color">Block Color:</label>
<input type="color" id="block-color" />
<br/><br/>
<label for="block-inside-color">Inside Color:</label>
<input type="color" id="block-inside-color" />
<br/><br/>
<label for="block-function">Function:</label>
<input type="text" id="block-function" />
<br/><br/>
<button onclick="createCustomBlock()">Create Custom Block</button>
`;
}
// Function to open theme changer
function openThemeChanger() {
document.getElementById('gui-content').innerHTML = `
<h3>Theme Changer</h3>
<label for="theme-select">Select Theme:</label>
<select id="theme-select">
<option value="cupcake">Cupcake</option>
<option value="candy">Candy</option>
<option value="dark">Dark</option>
<option value="marshmallow">Marshmallow</option>
<option value="bloody">Bloody</option>
<option value="image">Image</option>
</select>
<br/><br/>
<label for="theme-image-url" id="image-url-label" style="display: none;">Image URL:</label>
<input type="text" id="theme-image-url" style="display: none;" />
<br/><br/>
<button onclick="applyTheme()">Apply Theme</button>
`;
document.getElementById('theme-select').addEventListener('change', function() {
document.getElementById('image-url-label').style.display = this.value === 'image' ? 'block' : 'none';
document.getElementById('theme-image-url').style.display = this.value === 'image' ? 'block' : 'none';
});
}
// Function to open modifiers
function openModifiers() {
document.getElementById('gui-content').innerHTML = `
<h3>Modifiers</h3>
<label for="modifier-name">Modifier Name:</label>
<input type="text" id="modifier-name" />
<br/><br/>
<button onclick="addModifier()">Add Modifier</button>
<br/><br/>
<div id="modifiers-list"></div>
`;
}
// Populate block options for color changer
function populateBlockOptions() {
const blockSelect = document.getElementById('block-select-color');
// This example assumes some predefined blocks
// In practice, you might need to fetch block data from Scratch's editor API
const blocks = [
{ id: 'block1', name: 'Block 1' },
{ id: 'block2', name: 'Block 2' },
{ id: 'block3', name: 'Block 3' }
];
blocks.forEach(block => {
const option = document.createElement('option');
option.value = block.id;
option.textContent = block.name;
blockSelect.appendChild(option);
});
}
// Change block color
function changeBlockColor() {
const blockId = document.getElementById('block-select-color').value;
const color = document.getElementById('block-new-color').value;
const insideColor = document.getElementById('block-inside-color').value;
console.log(`Changing block ${blockId} color to ${color}, inside color ${insideColor}`);
// Implement the actual API call to change the block color
}
// Create custom block
function createCustomBlock() {
const name = document.getElementById('block-name').value;
const color = document.getElementById('block-color').value;
const insideColor = document.getElementById('block-inside-color').value;
const func = document.getElementById('block-function').value;
console.log(`Creating custom block: ${name}, Color: ${color}, Inside Color: ${insideColor}, Function: ${func}`);
// Implement the actual API call to create a custom block
}
// Apply theme
function applyTheme() {
const theme = document.getElementById('theme-select').value;
const imageUrl = document.getElementById('theme-image-url').value;
console.log(`Applying theme: ${theme}, Image URL: ${imageUrl}`);
// Implement the actual API call to apply the theme
}
// Add modifier
function addModifier() {
const name = document.getElementById('modifier-name').value;
const modifiersList = document.getElementById('modifiers-list');
const div = document.createElement('div');
div.textContent = name;
modifiersList.appendChild(div);
console.log(`Added modifier: ${name}`);
}
// Close the GUI
function closeGUI() {
document.getElementById('scratch-custom-gui').style.display = 'none';
}
// Initialize GUI creation
createAndOpenGUI();
})();