Rebranding the Editor
You probably want to give your mod a unique look, here are some things you can do to do that.
To an extent, you must rebrand your mod as you can't use Scratch's trademarks. Scratch's trademarks are things like the name Scratch, their logos and their mascots (like Scratch Cat and Gobo). However, you should be fine giving credit to Scratch. 7.3 Scratch Team Marks. You may not use any tradenames, trademarks, logos, or other marks owned or controlled by the Scratch Team, including, but not limited to, the Scratch Cat, the Scratch logo, ScratchJr, Giga, Nano, Pico, Terra, Milli, and Zepto (collectively, the “Scratch Team Marks”) except solely for your personal, educational, and non-commercial purposes in direct connection with your use of the Service to create and share Scratch projects as otherwise permitted herein. Any commercial use of the Scratch Team Marks will be subject to the terms of a separate license agreement negotiated between you and the Scratch Team, if any, provided that the Scratch Team is not obligated to grant any rights or licenses for any commercial use and may deny a license request for any or no reason in the Scratch Team’s sole discretion. You acknowledge that we are the sole owner of the Scratch Team Marks and any and all goodwill associated therewith. You agree that you will not do anything inconsistent with such ownership and that all use by you of the Scratch Team Marks will inure to the benefit of the Scratch Team. You agree further that nothing in these Terms will be construed as granting to you any right, title or interest in the Scratch Team Marks, other than the right to use the Scratch Team Marks as expressly provided in these Terms. You agree that you will not contest, oppose, or challenge our ownership of or title to the Scratch Team Marks or contest, oppose or challenge the validity of the Scratch Team Marks. You further agree that you have no power or right to and will not during the term of these Terms or thereafter contest, oppose or challenge the title or any rights of the Scratch Team in or to the Scratch Team Marks, alone or with other elements; claim any right, title, or interest in or to the Scratch Team Marks, alone or with other elements adverse to the Scratch Team; or register or apply for registration of the Scratch Team Marks anywhere, alone or with other elements. You agree that your use of any Scratch Team Marks permitted under these Terms or pursuant to any separate license will comply with any guidelines provided by Scratch to you. You agree that you will cease all uses of Scratch Team Marks immediately upon the Scratch Team’s request that you cease such uses and the Scratch Team will have no liability to you for your being required to cease such use. You hereby assign and will assign in the future to us all rights you may acquire by operation of law or otherwise in the Scratch Team Marks, including all applications or registrations therefor, along with the goodwill associated therewith.Scratch Terms of Service quote
Changing the Scratch logo
You can change the logo by replacing the SVG located at scratch-editor/packages/scratch-gui/src/components/menu-bar/scratch-logo.svg.
Changing the default project (including Scratch Cat)
The default project is located at scratch-editor/packages/scratch-gui/src/lib/default-project.
| File | Format | Contents |
|---|---|---|
0fb9be3e8397c983338cb71dc84d0b25.svg | SVG Image | costume2 (Scratch Cat) |
83a9787d4cb6f3b7632b4ddfebf74367.wav | Wave Sound | pop |
83c36d806dc92327b9e7049a565c6bff.wav | Wave Sound | Meow |
bcf454acf82e4504149f7ffe07081dbc.svg | SVG Image | costume1 (Scratch Cat) |
cd21514d0531fdffb22204e0ec5ed84a.svg | SVG Image | backdrop1 |
index.ts | JavaScript | List of contents of the project. |
project-data.ts | JavaScript | Contains the project.json. |
Changing the colours
Scratch's colours are defined in scratch-editor/packages/scratch-gui/src/css/colors.css. Below is a table of all the colours and a screenshot of the editor showing an example of where that colour is used. These screenshots do not include all uses of the colour.
| Variable Name | Default Value | Usage Screenshot | |
|---|---|---|---|
$ui-primary | hsla(215, 100%, 95%, 1) | Screenshot | |
$ui-secondary | hsla(215, 75%, 95%, 1) | Screenshot | |
$ui-tertiary | hsla(215, 50%, 90%, 1) | Screenshot | |
$ui-motion-overlay | hsla(215, 100%, 65%, 0.9) | Screenshot | |
$ui-white | hsla(0, 100%, 100%, 1) | Screenshot | |
$ui-white-dim | hsla(0, 100%, 100%, 0.75) | Screenshot | |
$ui-white-transparent | hsla(0, 100%, 100%, 0.25) | Screenshot | |
$ui-transparent | hsla(0, 100%, 100%, 0) | Screenshot | |
$ui-black-transparent | hsla(0, 0%, 0%, 0.15) | Screenshot | |
$text-primary | hsla(225, 15%, 40%, 1) | Screenshot | |
$text-primary-transparent | hsla(225, 15%, 40%, 0.75) | Screenshot | |
$motion-primary | hsla(215, 100%, 65%, 1) | Screenshot (also loading screen) | |
$motion-tertiary | hsla(215, 60%, 50%, 1) | Unused | |
$looks-primary | hsla(260, 60%, 60%, 1) | Screenshot | |
$looks-transparent | hsla(260, 60%, 60%, 0.35) | Screenshot | |
$looks-light-transparent | hsla(260, 60%, 60%, 0.15) | Screenshot | |
$looks-secondary-dark | hsla(260, 42%, 51%, 1) | Screenshot | |
$red-primary | hsla(20, 100%, 55%, 1) | Screenshot | |
$red-tertiary | hsla(20, 100%, 45%, 1) | Screenshot | |
$sound-primary | hsla(300, 53%, 60%, 1) | Screenshot | |
$sound-tertiary | hsla(300, 48%, 50%, 1) | Screenshot | |
$control-primary | hsla(38, 100%, 55%, 1) | Screenshot | |
$data-primary | hsla(30, 100%, 55%, 1) | Screenshot | |
$pen-primary | hsla(163, 85%, 40%, 1) | Screenshot | |
$pen-transparent | hsla(163, 85%, 40%, 0.25) | Screenshot | |
$pen-tertiary | hsla(163, 86%, 30%, 1) | Screenshot | |
$error-primary | hsla(30, 100%, 55%, 1) | Screenshot | |
$error-light | hsla(30, 100%, 70%, 1) | No screenshot. | |
$error-transparent | hsla(30, 100%, 55%, 0.25) | Screenshot | |
$extensions-primary | hsla(163, 85%, 40%, 1) | Screenshot | |
$extensions-tertiary | hsla(163, 85%, 30%, 1) | No screenshot. | |
$extensions-transparent | hsla(163, 85%, 40%, 0.35) | No screenshot. | |
$extensions-light | hsla(163, 57%, 85%, 1) | No screenshot. | |
$drop-highlight | hsla(215, 100%, 77%, 1) | Screenshot |
Changing the project file extension
There are a few places you need to change to adjust the project file extension.
-
Adjust thescratch-editor/packages/scratch-gui/src/containers/sb3-downloader.jsx
const getProjectFilename = (curTitle, defaultTitle) => {
let filenameTitle = curTitle;
if (!filenameTitle || filenameTitle.length === 0) {
filenameTitle = defaultTitle;
}
return `${filenameTitle.substring(0, 100)}.sb3`;
};.sb3with your own extension. -
Add your extension to the list of accepted extensions.scratch-editor/packages/scratch-gui/src/lib/sb-file-uploader-hoc.jsx
createFileObjects () {
// redo step 7, in case it got skipped last time and its objects are
// still in memory
this.removeFileObjects();
// create fileReader
this.fileReader = new FileReader();
this.fileReader.onload = this.onload;
// create <input> element and add it to DOM
this.inputElement = document.createElement('input');
this.inputElement.accept = '.sb,.sb2,.sb3';
this.inputElement.style = 'display: none;';
this.inputElement.type = 'file';
this.inputElement.onchange = this.handleChange; // connects to step 3
document.body.appendChild(this.inputElement);
// simulate a click to open file chooser dialog
this.inputElement.click();
} -
You will need to adjust the regular expression used. Here is a template you can use:scratch-editor/packages/scratch-gui/src/lib/sb-file-uploader-utils.js
export const getProjectTitleFromFilename = fileInputFilename => {
if (!fileInputFilename) return '';
// only parse title with valid scratch project extensions
// (.sb, .sb2, and .sb3)
const matches = fileInputFilename.match(/^(.*)\.sb[23]?$/);
if (!matches) return '';
return matches[1].substring(0, 100); // truncate project title to max 100 chars
};/^(.*)\.(sb[23]?|YOUR_EXTENSION_HERE)$/. -
This is not directly related to the project extension, but you should adjust it still. You should keep the start of the MIME type the same (scratch-editor/packages/scratch-vm/src/virtual-machine.js
/**
* @returns {string} Project in a Scratch 3.0 JSON representation.
*/
saveProjectSb3 () {
const soundDescs = serializeSounds(this.runtime);
const costumeDescs = serializeCostumes(this.runtime);
const projectJson = this.toJSON();
// TODO want to eventually move zip creation out of here, and perhaps
// into scratch-storage
const zip = new JSZip();
// Put everything in a zip file
zip.file('project.json', projectJson);
this._addFileDescsToZip(soundDescs.concat(costumeDescs), zip);
return zip.generateAsync({
type: 'blob',
mimeType: 'application/x.scratch.sb3',
compression: 'DEFLATE',
compressionOptions: {
level: 6 // Tradeoff between best speed (1) and best compression (9)
}
});
}application/x.).
Changing the sprite file extension
There are a few places you need to change to adjust the sprite file extension.
-
Add your sprite file extension toscratch-editor/packages/scratch-gui/src/components/sprite-selector/sprite-selector.jsx
<ActionMenu
className={styles.addButton}
img={spriteIcon}
moreButtons={[
{
title: intl.formatMessage(messages.addSpriteFromFile),
img: fileUploadIcon,
onClick: onFileUploadClick,
fileAccept: '.svg, .png, .bmp, .jpg, .jpeg, .sprite2, .sprite3, .gif',
fileChange: onSpriteUpload,
fileInput: spriteFileInput,
fileMultiple: true
}, {
title: intl.formatMessage(messages.addSpriteFromSurprise),
img: surpriseIcon,
onClick: onSurpriseSpriteClick // TODO need real function for this
}, {
title: intl.formatMessage(messages.addSpriteFromPaint),
img: paintIcon,
onClick: onPaintSpriteClick // TODO need real function for this
}, {
title: intl.formatMessage(messages.addSpriteFromLibrary),
img: searchIcon,
onClick: onNewSpriteClick
}
]}
title={intl.formatMessage(messages.addSpriteFromLibrary)}
tooltipPlace={isRtl(intl.locale) ? 'right' : 'left'}
onClick={onNewSpriteClick}
/>fileAccept. -
Changescratch-editor/packages/scratch-gui/src/containers/target-pane.jsx
handleExportSprite (id) {
const spriteName = this.props.vm.runtime.getTargetById(id).getName();
const saveLink = document.createElement('a');
document.body.appendChild(saveLink);
this.props.vm.exportSprite(id).then(content => {
downloadBlob(`${spriteName}.sprite3`, content);
});
}sprite3to your sprite file extension. -
This is not directly related to the sprite extension, but you should adjust it still. You should keep the start of the MIME type the same (scratch-editor/packages/scratch-vm/src/virtual-machine.js
exportSprite (targetId, optZipType) {
const soundDescs = serializeSounds(this.runtime, targetId);
const costumeDescs = serializeCostumes(this.runtime, targetId);
const spriteJson = this.toJSON(targetId);
const zip = new JSZip();
zip.file('sprite.json', spriteJson);
this._addFileDescsToZip(soundDescs.concat(costumeDescs), zip);
return zip.generateAsync({
type: typeof optZipType === 'string' ? optZipType : 'blob',
mimeType: 'application/x.scratch.sprite3',
compression: 'DEFLATE',
compressionOptions: {
level: 6
}
});
}application/x.).
Scratch commit hashes at the time of this tutorial
scratch-editor: 810ac12eaa1a1eb19d05fcb37f486ad1c4c56314
scratch-blocks: bb2f7ce297e2552767b531c212b18ee4f046e92d