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 the name Scratch, the Scratch logo, the Scratch Day logo, Scratch Cat and Gobo. However, you can use them to give credit to the original Scratch.
5.4 The Scratch name, Scratch logo, Scratch Day logo, Scratch Cat, and Gobo are Trademarks owned by the Scratch Team. The MIT name and logo are Trademarks owned by the Massachusetts Institute of Technology. Unless you are licensed by Scratch under a specific licensing program or agreement, you may not use these logos to label, promote, or endorse any product or service. You may use the Scratch Logo to refer to the Scratch website and programming language.
Changing the Scratch logo
You can change the logo by replacing the SVG located at scratch-gui/src/components/menu-bar/scratch-logo.svg
.
Changing the default project (including Scratch Cat)
The default project is located at 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.js | JavaScript | List of contents of the project. |
projectData.js | JavaScript | Contains the project.json . |
Changing the colours
Scratch's colours are defined in 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-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`;
};.sb3
with your own extension. -
Add your extension to the list of accepted extensions.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-gui/src/lib/sb-file-uploader-hoc.jsx
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-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-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-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);
});
}sprite3
to 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-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-gui: db1933b2aea9f9dbe51e0ad2d750a2550179314a
scratch-vm: d6420c4c9826d360adee118e0e9e255536be7f7c
scratch-blocks: 686df65cc6b5b3df37dc3204f56f443aa18c5085