2D editor tools
Open a scene with camera_2d. The tool strip appears over the Metal viewport in both editions of the editor. Select an object in Scene, or use Select and click its art. Tools are disabled during Play, rehearsal preview, and another builder's workspace. All saved edits use the existing command bus and History. Undo and Redo work on a whole gesture. Escape cancels an unfinished gesture without changing the scene.
Paint tiles
Select an existing tilemap, then choose Tiles. Click a picture in its tileset palette. Scroll over the palette to reach more tiles. The palette shows the tileset's declared characters, art, and terrain rules.
- Paint: drag across cells. Fast mouse movements fill the cells between samples.
- Erase: drag to replace cells with
.. - Rectangle: drag from one corner to another; both end cells are included.
- Flood: click to replace the connected area of the same character. It uses four neighbours, stops at map edges, and respects shorter rows.
- Pick: click a map cell to select its tile without adding an undo entry.
- Terrain: pick a terrain tile and paint. The renderer uses the existing
wall16orblob47rules to choose edges and corners from neighbouring characters, exactly astilemap_paint_regiondoes.
The brush edits within existing rows; map creation and row expansion remain in the Inspector. Painted cells preview in teal and erased cells in red. Release the mouse to commit the entire stroke.
Sprite animation
Select a sprite with named sprite.clips and click Animate. The floating panel shows the clips and a scrollable strip of actual sheet frames. Click or drag along the strip to scrub. Play and Pause preview the clip using anim_2d.frame_times; a one-shot stops at its last frame. Preview does not run gameplay or fire events.
Click a frame, enter its duration in seconds and its event names, then Apply frame. Separate multiple events with semicolons, for example footstep; sound:step. Durations must be between 0.001 and 60 seconds. Frame indexes in saved events are local to the clip, starting at zero, even when the clip starts later in the sheet.
Onion skins show the previous and next frames at low opacity behind the selected frame. The contact canvas shows art facing right in sprite world units, with a cross at its pivot. Select hit or hurt, then drag a rectangle. Drag inside an existing frame-specific box to move it, or drag a corner to resize it. Clear box removes that frame's box of the chosen kind. Red means hit, green means hurt, and yellow marks the editable box. Broader clip/range/wildcard boxes remain visible and unchanged; edit those rules in Inspector. Each frame supports one editable hit box and one editable hurt box through this panel. The runtime continues to support additional boxes.
Collision shapes
Select an object and choose Body box. Drag a new rectangle, drag inside its box to move the offset, or drag a corner handle to resize it. The tool writes the body's bottom-centred size and offset; drawing a box clears an existing polygon. Other body settings remain intact.
Choose Body polygon and click its vertices. Return (or double-click the last point) commits the outline. Existing vertices have handles; drag one to reshape it, or drag inside the outline to move the collision footprint. The engine uses a convex hull, so concave dents and holes do not become collision holes. Solid bodies use polygon collision; moving body kinds still use their boxes.
Trace art reads the selected sheet frame's alpha and shows a proposed convex outline in pink. Return accepts it; Escape discards it. Transparent margins, pivot, pixels per unit, flips and sprite scale are taken into account. The proposal samples at most 512 pixels on its longest side. It is a starting point: for a top-down tree, draw the trunk's footprint rather than accepting the entire canopy. Tracing does not change the body kind of an existing body.
Move, turn, resize and sort
Move and Scale show X and Y handles; drag an axis tip to constrain that axis, or drag elsewhere for both axes. Rotate uses a ring and turns around the object's origin. Pixel snap uses the pixel-perfect camera grid, or the selected sprite's pixels per unit (one world unit without either), for positions and displayed sprite size. Tile snap uses the selected map's size and origin, or the first map's grid when editing a sprite. Without a map it uses 64 units. No snap permits free placement. Rotation snaps to 15 degrees with snapping on.
Sort feet moves sprite.sort_offset vertically and enables y_sort. The red handle is the depth-sort origin, not a change to the sprite's art pivot. Camera room and Roof area draw their boxes and provide corner resize and inside move gestures; drag outside an existing box to draw a replacement. Those tools preserve the other fields of camera_zone_2d and roof_2d. Set the roof group and room behaviour in Inspector.
During a drag, handles preview the proposed values. The Metal scene changes on mouse-up. If another command changes the scene during the drag, the stale gesture is discarded. Animation playback and all tool settings are session-local; these tools do not write editor defaults.
Validation and pictures
TTREditor2DTests tests the real command bus, undo and redo, terrain rules, alpha tracing, and AppKit tool gestures. Its snapshot test creates a temporary project, renders the scene through the engine's Metal renderer, and captures the tool views using the same AppKit bitmap route as the editor snapshot command. It never connects to an existing editor or writes owner defaults. Pictures go to Lab/2d-tools in the build bay source tree (or EDITOR_2D_PICTURES). See root STATUS.md for actual test results and copied picture paths; having a test in source is not a PASS.
For a separate interactive check, copy the built executable to TTREditor2DToolsTest alongside its resource bundles and use a disposable project, -agentPort 7391 -noMouseCapture YES -noRemotePad YES. Check that 7391 is free first. Never reuse Gordon's running editor, its project, or its defaults. Stop only the test copy's PID.