Plugins can be switched on and off in the Plugins tab (#114)
1 parent
0576bbaccb
commit
de58de1d95
5 files changed
+39
-16
No files matched your search
+3
-2
@@ -16,8 +16,9 @@ All routes go through `api/index.php?r=…` (the site's nginx does not pass `PAT
|
||||
| GET | `sounds` | `[{file,name,bytes,updatedAt}]` — what the sound picker offers |
|
||||
| POST | `sounds&name=jump.wav` | **raw sound bytes** → `{file,name,bytes}` (201) |
|
||||
| DELETE | `sounds/{file}` | 204 |
|
||||
| GET | `plugins` | `[{file,bytes,updatedAt}]` — every `.js` in `data/plugins/`, sorted by file name |
|
||||
| GET | `plugins/{file}` | the module source as `text/javascript` (`nosniff`, `no-cache`); 404 for anything but a bare file name there — see [Plugins](Plugins) |
|
||||
| GET | `plugins` | `[{file,bytes,updatedAt,active}]` — every `.js` in `data/plugins/`, sorted by file name, switched on or not |
|
||||
| GET | `plugins/{file}` | the module source as `text/javascript` (`nosniff`, `no-cache`); 403 while the plugin is switched off, 404 for anything but a bare file name there — see [Plugins](Plugins) |
|
||||
| PUT | `plugins/{file}` | `{active}` → the entry as above. Switches a plugin on or off, server-wide, stored in `data/plugins/plugins.json`; 422 when `active` is not a boolean |
|
||||
|
||||
Every project document carries `formatVersion` (`PROJECT_FORMAT_VERSION` in `core/model/Project.ts`,
|
||||
currently 2). There are no load-time migrations: `serialize.ts` reads what it recognises and drops
|
||||
|
||||
+2
-2
@@ -89,7 +89,7 @@ src/editor/ App → Editor (layout + ticker), PlaySession (the run),
|
||||
FilePicker (the shared "+ → Texture / Font / Sound" dialog; ImagePicker/FontPicker/SoundPicker only describe their row),
|
||||
framing (fit/marquee/snap maths), FormDialog (the small modal forms: label column, Cancel + confirm, one open at a time), AssetTabEditor (the shared shell of the asset tabs),
|
||||
TabStrip + tabRow (the tab row and what it does when the tabs outgrow it; plugin tabs are appended at run time)
|
||||
src/editor/plugins/ startPlugins (list, import, host) → loader (order, checks, what became of each file), pluginApi (API v1), NodeBoard (api.ui)
|
||||
src/editor/plugins/ startPlugins (list, import, host) → loader (PluginManager: order, checks, switching on and off, what became of each file), pluginApi (API v1, the per-plugin scope), PluginsPane (the Plugins tab), NodeBoard (api.ui)
|
||||
src/editor/viewport/ WorldViewport base → FreeViewport (a camera of its own: fit, pan, wheel zoom) → SceneViewport, PreviewCanvas;
|
||||
GameViewport follows the game's camera instead — editing tools, hence not in src/viewport/
|
||||
src/editor/inspector/ Inspector panel, host (what a section builds into), field factory, previewHandlers (scrub → preview → command), valueSpecs
|
||||
@@ -113,7 +113,7 @@ src/editor/list/ ListEditor (a row per item), slot (which list is being ed
|
||||
src/editor/console/ log (ring buffer, argument formatting, the console.* capture), ConsolePanel (the tail under the tabs)
|
||||
api/ PHP backend: index.php (routing), lib/{Store,TextureStore,FontStore,SoundStore,PluginStore,OriginalName,Response}.php
|
||||
data/projects/ persisted projects, data/textures/ + data/fonts/ + data/sounds/ content-addressed uploads,
|
||||
data/plugins/ editor plugins (filled from plugins/ by the build and the seeder)
|
||||
data/plugins/ editor plugins and plugins.json (which are switched on); filled from plugins/ by the build and the seeder
|
||||
tests/ Vitest unit tests tools/ seed-*, e2e (steps in tools/e2e/, rig in tools/e2e/lib/), smoke-*, lib/, assets/ (the walk demo's sheet)
|
||||
```
|
||||
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs
|
||||
# code is lost (tail's is reported), so a red run reads as green
|
||||
npm run build # writes dist/ and regenerates index.html
|
||||
./build.sh # the same under `set -o pipefail`, for callers that pipe the output
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 963 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 969 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
|
||||
./e2e.sh start [GM_STEPS] # the same run detached, see below
|
||||
./e2e.sh status # live progress, or the last run's result
|
||||
@@ -232,4 +232,4 @@ widths to find click points. The **render device is not in this repo** — `/dev
|
||||
and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which
|
||||
applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets
|
||||
WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`,
|
||||
WebGL 2.0, and the same 963 checks as here.
|
||||
WebGL 2.0, and the same 969 checks as here.
|
||||
+1
-1
@@ -31,7 +31,7 @@ Live: <https://nockal.com/game-maker/> · Widget playground: <https://nockal.com
|
||||
| [Architecture](Architecture) | The stack, the source layout, the rules that keep it organised |
|
||||
| [Development](Development) | Commands, the GPU requirement, the e2e suite, the three example games, continuous integration |
|
||||
| [API](API) | The PHP JSON API and the project document |
|
||||
| [Plugins](Plugins) | Extending the editor: the plugin file, how it is loaded, API v1, the demo plugin |
|
||||
| [Plugins](Plugins) | Extending the editor: the plugin file, how it is loaded, switching one on and off, API v1, the demo plugin |
|
||||
|
||||
## Ideas, gaps and bugs
|
||||
|
||||
|
||||
+31
-9
@@ -2,11 +2,12 @@ A **plugin** extends the editor. It is one JavaScript file – an ES module –
|
||||
server, and the editor loads every file there when it starts. v1 is deliberately small: it offers what
|
||||
the demo plugin needs (read the assets, add a tab, show nodes on a board) and nothing it does not.
|
||||
|
||||
**Where plugins come from.** Every `.js` file in `data/plugins/` is active; there is no switch yet
|
||||
(#114) and no upload (#116) – a file is put there by hand. The plugins that ship with the repository
|
||||
**Where plugins come from.** A file is put into `data/plugins/` by hand; there is no upload yet
|
||||
(#116). A file put there is **off** until someone switches it on in the **Plugins** tab (#114). The plugins that ship with the repository
|
||||
live in `plugins/` and are copied to `data/plugins/` by `npm run build` and by `tools/seed-e2e.mjs`;
|
||||
a file of the same name is replaced, anything else in the folder is left alone. `data/plugins/` is
|
||||
not in the repository. The setting is **server-wide**: every project on the server sees the same
|
||||
a file of the same name is replaced, anything else in the folder is left alone, and a shipped
|
||||
plugin is switched on – the build only when the state does not name it yet, the seeder always.
|
||||
`data/plugins/` is not in the repository. The setting is **server-wide**: every project on the server sees the same
|
||||
plugins. Plugins run **in the editor only**, never in a running game or an export.
|
||||
|
||||
## The format
|
||||
@@ -25,7 +26,7 @@ export function activate(api) {
|
||||
| `meta.name`, `meta.version` | Shown in reports; the name falls back to the id. |
|
||||
| `meta.api` | The plugin API version the plugin was written for. Anything but `1` is not activated. |
|
||||
| `activate(api)` | Required. Called once at start-up; may be `async`, and the next plugin waits for it. |
|
||||
| `deactivate()` | Optional. Nothing calls it yet – it is for switching a plugin off (#114). |
|
||||
| `deactivate()` | Optional. Called when the plugin is switched off, before what it registered is taken away. |
|
||||
|
||||
**A plugin imports nothing.** Everything comes in through `api`. The editor is one WebGL canvas
|
||||
with one Pixi instance: a plugin that brought its own Pixi would draw into a second renderer. For
|
||||
@@ -33,9 +34,9 @@ the same reason `api.tabs.add` accepts only widgets from `api.ui`.
|
||||
|
||||
## Loading
|
||||
|
||||
The editor asks `GET ?r=plugins` for the list, then imports each file through
|
||||
The editor asks `GET ?r=plugins` for the list, then imports each **switched-on** file through
|
||||
`GET ?r=plugins/{file}` (see [API](API)) – **in file-name order**, one after the other, after the
|
||||
project has loaded. Nothing a plugin does wrong stops the editor or the other plugins. Each of these
|
||||
project has loaded. A plugin that is off is never fetched, so none of its code runs. Nothing a plugin does wrong stops the editor or the other plugins. Each of these
|
||||
leaves the plugin inactive, with a line in the console and a notice in the toolbar:
|
||||
|
||||
- the file does not load (a syntax error, a failed request),
|
||||
@@ -44,7 +45,28 @@ leaves the plugin inactive, with a line in the console and a notice in the toolb
|
||||
- a plugin with the same `meta.id` is active already,
|
||||
- `activate` throws (or its promise rejects).
|
||||
|
||||
What `activate` registered before it threw stays registered.
|
||||
What `activate` registered before it threw is taken away again, so a half-built plugin leaves
|
||||
no tab behind.
|
||||
|
||||
## Switching a plugin on and off
|
||||
|
||||
The **Plugins** tab lists every file in `data/plugins/` with its name, version, file and state, each
|
||||
with a switch. The state is stored on the server in `data/plugins/plugins.json`
|
||||
(`{"demo-plugin.js": {"active": true}}`), so it holds for everyone who opens this editor, for every
|
||||
project.
|
||||
|
||||
A switch takes effect at once, without reloading the editor:
|
||||
|
||||
- **On** stores it, then loads and activates the plugin – after every plugin that is running
|
||||
already, whatever the file names say.
|
||||
- **Off** stores it, calls the plugin's `deactivate()`, and then takes away what it registered
|
||||
through the API: its tabs, their content and its `change` listeners. Whoever was looking at one
|
||||
of its tabs lands on Scene.
|
||||
- A plugin that is off has no name on its row until it has run once in this session: reading a name
|
||||
out of it would mean running it.
|
||||
- What the plugin did outside the API – a timer it started, something it wrote to the server – the
|
||||
editor cannot take back. That is the same right-to-everything as in **Limits** below.
|
||||
- When the server does not store the switch, nothing changes and the toolbar says why.
|
||||
|
||||
## API v1
|
||||
|
||||
@@ -69,4 +91,4 @@ creating, renaming or deleting an asset shows at once. e2e step 38 checks exactl
|
||||
for v1, open in #115.
|
||||
- No writing to the project, no node types of its own, no asset types, no inspector rows, no hooks
|
||||
into a running game. Those come when a plugin needs them.
|
||||
- No switch to turn a plugin off (#114), no upload (#116).
|
||||
- No upload (#116): a file is put into `data/plugins/` by hand.
|
||||
Reference in new issue
Block a user