Spaces:
Sleeping
Sleeping
File size: 13,409 Bytes
7aec436 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
# Scaffolding API
## Scaffolding's API is in an ALPHA state. It WILL change in ways that are backwards incompatible. Please pin to exact versions to avoid pain later!
## This documentation is very work in progress. Report any errors you find or any issues you encounter.
Scaffolding is the project player used by the packager.
Here's what Scaffolding does for you:
- Loads the entire Scratch VM and connects everything together
- Forwards user input to Scratch and implements things like sprite dragging
- Removes unnecessary parts of Scratch that you don't need just for running projects
- Implements the "ask and wait" block
- Implements highly optimized (much faster than scratch-gui) variable and list monitors with context menus and file dropping
- Implements cloud variables using a Scratch-compatible WebSocket server or local storage
- Implements video sensing
Here's what Scaffolding doesn't do for you:
- Green flag screen
- Controls
- A progress bar
## Versions
There are two versions of Scaffolding:
- scaffolding-full (4.6MB) - contains every part of Scratch
- scaffolding-min (2.5MB) - contains all of Scratch EXCEPT sound files used by the music extension. Significantly smaller than scaffolding-full.
Scratch is a large application so either script is very large. If you don't need the music extension to function, use scaffolding-min.
## Supported environments
Scaffolding strives to support any web browser released in 2018 or later.
Scaffolding only runs in web browsers. It will not run in Node.js.
## Content-Security-Policy
Meaningfully sandboxing Scaffolding with a Content-Security-Policy is hard. It needs to be able to fetch things from `data:` and `blob:` URLs, and the compiler (enabled by default) requires `unsafe-eval`.
This section will be updated later with more guidance.
## Installing
Scaffolding is distributed as one big JavaScript file. Any supplemental CSS etc. is stored inside the JS file.
We make no promise of having a stable API between even minor releases as Scaffolding is effectively just an implementation detail of the packager, which is why it's very important to lock your application to specific versions.
You can only load one version of Scaffolding on a page, but you can create as many Scaffolding project players as you'd like.
### From a CDN
```html
<!-- for scaffolding-min: -->
<script src="https://cdn.jsdelivr.net/npm/@turbowarp/packager@0.0.0/dist/scaffolding/scaffolding-min.js"></script>
<!-- for scaffolding-full -->
<script src="https://cdn.jsdelivr.net/npm/@turbowarp/packager@0.0.0/dist/scaffolding/scaffolding-full.js"></script>
```
Replace `0.0.0` with the latest release from https://github.com/TurboWarp/packager/releases, for example `1.0.0`.
DO NOT use versions like `@1` or `@latest` -- your website will break if (when) Scaffolding's API changes!
If you don't want to use a CDN, you can download the JS file linked by the script tag to a server you control and simply load that script instead.
### From npm
```bash
npm install --save-exact @turbowarp/packager
```
```js
// for scaffolding-min:
require('@turbowarp/packager/dist/scaffolding/scaffolding-min.js');
// for scaffolding-full:
require('@turbowarp/packager/dist/scaffolding/scaffolding-full.js');
// or, if you prefer ES6 imports,
// for scaffolding-min:
import '@turbowarp/packager/dist/scaffolding/scaffolding-min.js';
// for scaffolding-full:
import '@turbowarp/packager/dist/scaffolding/scaffolding-full.js';
```
Note that regardless of how you import Scaffolding, it is exported on `window.Scaffolding`, not on the module. This is strange and weird; it may change in the future.
## Usage
For an example, see [../static/example.html](../static/example.html). You can also examine the output of files generated by the packager.
At this point you should have Scaffolding installed on `window.Scaffolding`.
### Setup
Create an instance of Scaffolding:
```js
const scaffolding = new Scaffolding.Scaffolding();
```
You should be able to have multiple of these on one page if you want.
### Configuration
Certain Scaffolding options must be configured before you can finish setting up the Scratch environment. These are optional. The options that must be configured at this point are listed below along with their defaults.
```js
scaffolding.width = 480; // Custom stage width
scaffolding.height = 360; // Custom stage height
scaffolding.resizeMode = 'preserve-ratio'; // or 'dynamic-resize' or 'stretch'
scaffolding.editableLists = false; // Affects list monitors
```
### Finalize setup
This will actually create the Scratch VM, Renderer, Audio Engine, etc. and link them all together.
```js
scaffolding.setup();
```
### Put it in the DOM somewhere
You are responsible for making a location in the DOM for Scaffolding and using CSS to appropriately size it.
If your HTML looks like this:
```html
<style>
#project {
width: 480px;
height: 360px;
}
</style>
<div id="project"></div>
```
You would append Scaffolding to the DOM like this:
```js
scaffolding.appendTo(document.getElementById('project'));
```
Scaffolding will automatically resize the project player to fit inside the space you gave it. It listens for the window 'resize' event to do this. If you are resizing the element in a way that doesn't involve a window resize, you can manually call `scaffolding.relayout()` to force a resize. This can be slow, so don't do it when you don't need to.
### Tell it where to fetch projects and assets from
You have to manually configure scratch-storage to know where to fetch files from. If you want to load projects from scratch.mit.edu, you would do:
```js
const storage = scaffolding.storage;
storage.addWebStore(
[storage.AssetType.ImageVector, storage.AssetType.ImageBitmap, storage.AssetType.Sound],
(asset) => `https://assets.scratch.mit.edu/internalapi/asset/${asset.assetId}.${asset.dataFormat}/get/`
);
```
Downloading shared Scratch projects can be done manually with something like this:
```js
const id = '437419376';
const projectMetadata = await (await fetch(`https://trampoline.turbowarp.org/api/projects/${id}`)).json();
const token = projectMetadata.project_token;
const projectData = await (await fetch(`https://projects.scratch.mit.edu/${id}?token=${token}`)).arrayBuffer();
```
### Configure cloud variables
By default cloud variables are just normal variables. You must reconfigure this manually if you don't want that.
To synchronize cloud variables globally:
```js
const cloudVariableProvider = scaffolding.addCloudProvider(new Scaffolding.Cloud.WebSocketProvider('wss://clouddata.example.com', 'PROJECT ID HERE'));
```
To store cloud variables locally:
```js
const localStorageProvider = scaffolding.addCloudProvider(new Scaffolding.Cloud.LocalStorageProvider('UNIQUE STORAGE KEY (such as project ID) HERE'));
```
To use a different provider for different variables, there is an override system.
```js
scaffolding.addCloudProviderOverride("☁ my variable", cloudVariableProvider);
scaffolding.addCloudProviderOverride("☁ other variable", localStorageProvider);
```
### Set username
To change the value of the username block from the default empty string:
```js
scaffolding.setUsername("ExampleUser");
```
### Set accent color
To change the accent color used in prompts, context menus, etc.:
```js
scaffolding.setAccentColor("#abcdef");
```
The color MUST be a hex color code with 6 characters. 3 character codes will not work. The leading # is required. Color names will also not work.
### Load a project
At this point you can load a project. Scaffolding accepts an ArrayBuffer, Uint8Array, or string containing a full compressed project or a project.json.
Full compressed projects are full sb/sb2/sb3 files including assets.
project.json is just the JSON part of an sb2/sb3 file. In this case assets will be fetched separately.
```js
scaffolding.loadProject(projectData)
.then(() => {
// ...
})
.catch((error) => {
// ...
});
```
This returns a Promise that resolves when the project has finished loading or rejects if the project could not be loaded.
The project is not automatically started when loadProject completes.
If you configured scratch-storage to load projects from scratch.mit.edu, you can use:
```js
scaffolding.storage.load(Scaffolding.Storage.AssetType.Project, "PROJECT ID HERE eg. 104")
.then((projectDataAsset) => scaffolding.load(projectDataAsset.data))
.then(() => {
// ...
})
.catch((error) => {
// ...
});
```
### Start the project
This will start the project *and* start scripts that are supposed to run when you press the green flag.
If you want to automatically start the project, you can do:
```js
scaffolding.loadProject(/* ... */) // see previous step
.then(() => {
scaffolding.start();
});
```
If you want to display something like Scratch's green flag screen, you can create the screen yourself and call scaffolding.start() when the user clicks on it.
### Advanced topics
Scaffolding gives you direct access to various internal classes.
|Package|Instance|Constructor|
|:-:|:-:|:-:|
|scratch-vm|`scaffolding.vm`|`Scaffolding.VM`|
|scratch-render|`scaffolding.renderer`|`Scaffolding.Renderer`|
|scratch-storage|`scaffolding.storage`|`Scaffolding.Storage`|
|scratch-audio|`scaffolding.audioEngine`|`Scaffolding.AudioEngine`|
|JSZip|N/A|`Scaffolding.JSZip`|
Constructors are immediately available when scaffolding-[full|min].js is loaded. Instances are available after scaffolding.setup() is called.
The scratch-audio instance might be null if the browser doesn't support the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API). This is pretty rare to not be supported, but a few people do turn it off for one reason or another.
The scratch-storage constructor is actually a wrapper used for implementing progress monitoring.
### VM Settings
```js
// Press the green flag (like Scratch's green flag button)
scaffolding.greenFlag();
// Stop all (like Scratch's stop sign button)
scaffolding.stopAll();
// Turbo Mode
scaffolding.vm.setTurboMode(true);
// Framerate
scaffolding.vm.setFramerate(60);
// Interpolation
scaffolding.vm.setInterpolation(true);
// High quality pen
scaffolding.renderer.setUseHighQualityRender(true);
// Turn off the compiler
scaffolding.vm.setRuntimeOptions({enabled: false});
// Infinite clones, Remove miscellaneous limits, Remove fencing
scaffolding.vm.setRuntimeOptions({fencing: false, miscLimits: false, maxClones: Infinity});
// Load custom extension
// Do this before calling loadProject() for best results.
scaffolding.vm.extensionManager.loadExtensionURL('https://extensions.turbowarp.org/fetch.js');
// Do something when the project stops
vm.runtime.on('PROJECT_RUN_STOP', () => {
// ...
});
```
### Get or set variables and lists
```js
scaffolding.getVariable("global variable name"); // -> "Hello, world!"
scaffolding.getList("global list name"); // -> [1, 2, 3]
scaffolding.setVariable("global variable name", "New value");
scaffolding.setList("global list name", [4, 5, 6]);
```
Variables must be a number, string, or boolean, and lists can only contain numbers, strings, and booleans. The VM was not designed to handle these invalid values and will not behave properly. Invalid values will throw an error.
Lists returned by getList are returned by reference, so any changes you make to them will be reflected in the project. However, changes might not display on the any visible monitors unless you use setList.
### Progress monitoring
Scaffolding can't help you monitor the progress of the data you feed into loadProject() -- you have to do that on your own. That might mean using an XMLHttpRequest to fetch the data so you can listen to the progress event.
Scaffolding can help you monitor asset download progress.
```js
scaffolding.storage.onprogress = (totalAssets, loadedAssets) => {
// ...
};
```
Again, you are responsible for displaying a progress bar on your own.
### Fullscreen
Scaffolding doesn't have an API for fullscreen. Instead, just use the DOM fullscreen API on an element that contains scaffolding.
```js
document.getElementById('project').requestFullScreen();
```
### Advanced styling
You are free to override the styles for any class starting with `sc-`.
### Addons
In the same place as scaffolding-[full|min].js, there is a file called addons.js that contains some extra features. You can load it the same way you load the normal scaffolding script. It exports on window.ScaffoldingAddons instead.
```js
ScaffoldingAddons.run(scaffolding, {
// Enable what you want.
gamepad: false,
pointerlock: false,
specialCloudBehaviors: false,
unsafeCloudBehaviors: false,
pause: false, // Adds API: scaffolding.vm.setPaused(true)
});
```
### Exporting sb3
Here's something to get you started:
```js
Object.assign(document.createElement("a"), {
href: URL.createObjectURL(await scaffolding.vm.saveProjectSb3()),
download: 'project.sb3'
}).click();
```
|