## KilledByAPixel/LittleJS — v1.22.0…v1.23

_27 commits._

### Features
- **A game makes the level editors its own through levelEditor, the 2D and the 3D one by the same calls, from any build: addKey, addButton and addTool add a key, a panel button and a mouse tool of the game's own, a tool's press, drag and release one undo; onOpen, onClose, onUpdate, onDraw, onPanel and onSave are moments the editors call; edit2D and edit3D are the edit functions; LevelEditor is exported, its hooks are methods, and a class of the game's own that extends it is made the one in use with setLevelEditor; release builds have the same class doing nothing, so a game needs no guards. EDITOR.md is rewritten around it, its examples run from the file, and an ES module game and a release build are checked** (df7813a)

### Fixes
- **Review 2026-10-01 pass 4 fix: the example browser shows the example selected last, whatever order the files arrive in; a file that came in after another example was selected used to replace it, so stepping fast with Prev and Next could show one example's code under another's name, and a short still loading could take the place of a large example and leave its controls disabled** (5b5e6f6)
- **Review 2026-10-01 fix: the 3D editor's Scene box changes the scene as it is when an input is used; fog start and end, the sky colors and the sun's two sliders each kept the values from when the box was made, so a field edited right after another put the other back; a smoke page edits them in a row with the box in focus** (19407ff)

### Backend
- **Review 2026-10-01 pass 5 fixes: a Save takes its place in line when it is asked for and its onSave hook is asked when its turn comes, so an async hook that answers late can not write an older level over a newer one, in both editors; an attached prefab inside a prefab of separate parts is placed by its origin, it was off by how far its handle is from it; the body of an attached prefab is the box around its parts as they are turned. Docs rebuilt** (d7e5e2d)
- **Version 1.23.0, with the docs rebuilt: 3D prefabs and the prefab editor, the level editor extension API and EDITOR.md, the parallax plugin, touch pinch as the mouse wheel, the terrain flatten and paint brushes, a light's lens flare; the Parallax short draws its ground in front of the mountains; a DeepScan constant condition in Prefab3D is gone** (8937ed3)
- **Level editor extension API, the review's fixes: a moment a game sets to undefined is not called; a key is spelled one way for both editors, names in any case, Space, and punctuation by the key it is on in 3D; Escape, 0 and a modifier other than Ctrl are not taken, with a warning, and a digit of the game's own takes the place of the 2D editor's layer pick; in 2D Escape takes a tool's held press back, keys wait for a held press, and the editor's own brush and Shift line are not drawn under a game's tool, in 3D its Blocks and Terrain cursors are put away; onSave may be async and is asked for a prefab saved from inside it; edit3D.place refuses a type nobody added, mousePoint is undefined over the panel, edit2D.hover on an object layer, and a tool added again replaces the first; edit2D and edit3D are typed** (76ff053)
- **3D editor: Load prefab, a button after the Place list, adds a prefab from a file the editor saved to the level's own prefabs under the file's name, as one undo, and picks it to place; a file that is not a prefab or a name that is taken is refused, and the panel says why** (c939620)
- **EDITOR.md, making your own level editor: what a game hooks into to turn the 2D and 3D level editors into an editor for itself, written for a person or an AI assistant to follow; the hooks every build has, its own types and their properties as panel inputs, and in the script build its own keys and panel buttons through the editors' edit functions, with which build has what and what is not there yet; its code blocks marked as tested are run from the file by test/editorCustom.test.mjs; linked from the README and REFERENCE** (bd39e19)
- **Prefabs: an instance, or a plain object, that was cut pastes with its bottom on the ground, by the size it had when it was copied; an instance play took a part of is made whole when the editor opens; a prefab saved from inside it is not said to be unsaved on going back; tests for placing, pasting, Save inside a prefab and a level whose prefab is missing** (84ab59c)
- **The 3D Prefab Maker short shows the prefab alone: the ring of copies around it is gone, it read as part of what was being built** (28a1fbe)
- **Prefabs: an attached prefab's handle is at the middle of the box around its parts, as an object's place is the middle of its body, so setCollision makes it solid where it is seen, while a level still keeps it by its prefab's origin; a prefab made of the level being edited, or one that holds it, is not in the Place list and is not placed, so a prefab maker can not put its prefab inside itself; a prefab being edited is autosaved with its level as the level would be on going back, so a reload while one is open keeps the edits** (cc90732)
- **Prefabs, the final review's fixes: redo of Make prefab, undo of Reset to file and an autosave applied make the instance of a prefab that was not a type yet; inside a prefab the level's prefabs stay as they are, and Make prefab and Attached wait for the level; a prefab opened from a level made in code is the prefab and not that level's autosave; a prefab inside an attached prefab is attached too, its parts ride along; a scene set inside a prefab goes when it is left; a level the game loads while a prefab is open ends what was open; opening a prefab written without ids and going back changes nothing; the prefab that is open is not placed inside itself; the panel says which of the game's prefabs were edited and are in no file** (f385e54)
- **3D editor prefabs: Edit prefab, Enter on an instance, opens its prefab alone with an undo of its own, the level put away, and a prefab inside it the same way; Back, or Backspace with nothing selected, steps out, every instance follows, and what was edited in the level's own prefabs is one undo of the level; a prefab the game added is changed where the game keeps it, and Save inside a prefab writes its own file; closing the editor steps all the way out. The 3D Prefab Maker short is the level editor on one prefab, with a ring of copies that follows as it is built** (27a1ff6)
- **3D editor prefabs: Ctrl+G makes the selection a prefab of the level's own, about its bottom centre, with one instance where it was, and a name the level's prefabs have replaces that prefab for every instance; Ctrl+Shift+G unpacks an instance into its objects; the panel names a prefab, exports it to a file of its own and sets it attached** (f58088c)
- **3D prefabs in the level editor: an instance is one thing to select, move, land and outline, by the box around its parts; a level's own prefabs are a part of the level, undone, autosaved and saved with it, and a change to one makes every instance again; the Place list has the prefabs under their own label** (55c492e)
- **3D prefabs, the runtime: level3DAddPrefab adds a small level, objects about its own origin, as a type placed many times, and every instance follows the prefab; its instance is a Prefab3D, a handle whose parts are objects of their own in the world where its place, turn and size put them, solid as if placed by hand and kept with the handle, or, for an attached prefab, its children moving as one body; a prefab may hold prefabs, one that holds itself is stopped; a level's prefabs block is added when it loads; level3DSpawn makes one object of any type from code, level3DLoadPrefab fetches one** (90ed340)
- **A pinch of two fingers is the touch screen's mouse wheel: touchPinch is how far the fingers moved together or apart this frame, apart negative as the wheel turned up is, a click for every 50 pixels, and it is added to mouseWheel while touchPinchWheel is on, the default, so what zooms with the wheel zooms with a pinch; the mouse is between the two fingers, the button the first finger pressed lets go, and the finger left after a pinch moves the mouse with no press and no jump; setTouchPinchWheel(false) leaves the first finger the mouse as before, for a game with its own use for two fingers, and touchPinch can still be read** (12bcb7a)
- **README no longer lists the Stress Test example, which is gone** (b51490c)
- **remove stress test** (5a7baaf)
- **Parallax plugin: ParallaxLayer, a CanvasLayer that follows the camera by its parallax, 0 with the world and 1 with the screen, and repeats across the view, so a level of any width has a background; its image is drawn once by a function a game passes, or by parallaxMountains, a range of mountains whose ridge ends where it starts so it repeats with no seam; zoomFollow keeps a layer the same size on screen as the camera zooms; the Parallax short and the platformer use it in place of their own two copies of the same class, and the short is listed with the plugins; a smoke page checks the repeat and the follow on pixels** (aa3cf89)
- **The Terrain tool has three brushes, X goes to the next: sculpt as before, flatten, which brings the ground to the height pressed, and paint, which colors the ground, Shift taking the paint off; a level's terrain keeps its paint as a list of colors and runs along its rows, and level3DLoad gives the HeightMap its colors; a LensFlare3D with a light is that Light3D's flare in place of the sun's, at the light and in its color, smaller from farther than the light reaches, hidden by what is in front of it, a spotlight's only from inside its beam; the 3D editor's Move handles follow the object's own axes with own axes on, L or the panel; the example browser has Prev and Next buttons beside Restart, to go through the examples on a phone** (16f4337)
- **Low priority batch of our own 2026-10-01 review: a spotlight that casts the shadows lights no wider than its shadow map covers, a cone of 1.35, and a tiny one keeps a working map; an object whose box the camera is inside no longer hides the lens flare, nor does a destroyed voxel map; a 3D emitter makes its first particle at once as the 2D one does, an endless rate does not hang it, and a particle its collide callback destroyed gets no update callback and is gone that update; in the 3D editor the level's last Light that asks casts the shadows as lights are edited, an empty Map size field keeps the size, a fog number not taken shows the one it has, and the sun's height stops at 89; an effect's angle wraps around instead of clamping; the designer removes a game's own behavior by name and lists them after the known ones; an effect is sanitized once a play, a loaded library is not made text again, the lightmap of a canvas larger than the GPU's textures is made once, smoothing copies only the rows it reads** (97e0007)
- **Review fixes, 2026-10-01 pass 3 and our own pass: a SpriteAnimator read that ends a clip gives the clip its callback switched to; particle effect options are typed to take any setting; 3D particles grip where they land by ParticleEmitter3D.stick, which a level's friction does not undo; opening the 3D editor puts the blocks and terrain back as the level has them, so what play changed is not written into the level; a type picked to place is placed with the Blocks or Terrain tool on; a 3D light draws no plain square where its glow texture can not be made; the smoke runner opens one DevTools socket, cleans up from before Chrome starts, fails fast when Chrome is gone, takes over a stale lock and fails a listed short with no file; REFERENCE says a spotlight can cast the shadows** (b6f5dbc)
- **Review 2026-10-01 pass 2 fixes: a range set on a Sound after it is made is its range in 3D too, Sound.range is an accessor whose setter says the range is the sound's own; see-through blocks of a voxel map, glass, water and leaves, no longer hide the sun's lens flare, and a solid block behind them still does** (07ccba9)
- **The smoke suite is kept light on the machine it runs on: it and its Chrome run at below normal priority, a second run refuses to start while one is going, a run past 5 minutes stops itself, and Chrome is closed however the run ends; the reason for one Chrome and 4 tabs is written beside them** (3cf6c9a)
- **Smoke suite review: pages for a tile layer, 2D particles and texture filtering, for Canvas2D with WebGL off, for the 2D light system and its shadows, and for the 3D depth texture; the 3D page checks the sun's shadow on the ground, an object's own Shader, a voxel block and a height map; five checks that only said again what another says are gone** (8b0643f)
- **3D editor Blocks tool: box fill, X, a drag fills the whole rectangle from the press to the mouse as many layers tall as the panel's height, Shift clears it and Ctrl repaints it, growing out from the face pressed or into the blocks, with an outline of the box as it is dragged; Resize in the panel changes the map's size about its middle, its blocks staying where they are in the world** (10635e4)

_Recap by [Repo Wrapped](https://repowrapped.com/gh/KilledByAPixel/LittleJS?utm_source=github-action)._