Skip to content

2D: sprite animation, Camera2D controller and pixel-perfect rendering - #165

Merged
SpectralDragon merged 5 commits into
mainfrom
worktree-2d-sprite-animation
Oct 19, 2026
Merged

SpectralDragon merged 5 commits into
mainfrom
worktree-2d-sprite-animation

Conversation

@SpectralDragon

@SpectralDragon SpectralDragon commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

What

Sprite animation: SpriteAnimator plays clips of a shared .spriteanim resource (SpriteAnimationSet) on a Sprite. Frames are grid cells or pixel rectangles. Events for frame, marker, loop and finish. Aseprite JSON import (AsepriteSheet), AdaScript control through plain fields, and a Studio resource editor with preview, Aseprite import and Add to Scene. Docs: Documentation/SpriteAnimation.md.

Camera 2D: Camera2DController + CameraTarget2D: follow groups by weight, offset, dead zone, frame-rate-independent smoothing, limits (zoom/origin aware), zoom with smoothing, trauma shake with optional roll, pixel snapping. It runs after transform propagation and publishes the view itself (CameraSystem.refreshView), so the frame is extracted with the camera on its target's final position. Studio components and AdaScript fields included. Docs: Documentation/Camera2D.md.

Pixel-perfect rendering: Camera.pixelPerfect renders at a fixed resolution and presents with a whole-number scale (or fit), nearest sampling and a border. The projection uses the fixed size (one world unit = one art pixel at zoom 1); AdaUI is drawn onto the scaled picture at the output's own resolution, so UI stays crisp; pointer mapping and sprite picking measure against the picture. Studio's Camera component has the settings. Docs: Documentation/PixelPerfect.md. ADR-0022 records all three with validation.

Bugs found and fixed on the way

  • CameraSystem inserted a camera's first GlobalViewUniform while iterating its query, which moves the camera to another archetype; with several cameras some were skipped or visited twice. Regression test fails before the fix.
  • EditorSceneViewportView.uiProjectRoot(from:) looped forever when no ancestor folder holds a project marker (Foundation maps the parent of / to /../). It hung every scene load from a temp folder, including the existing sprite layout test.
  • GlobalTransform.init(matrix:) is now public (documented as for systems that publish a final matrix after propagation).
  • Camera2DControllerPlugin is installed by DefaultPlugins, not ScenePlugin, because it depends on TransformSystem and SceneNavigatorTests use ScenePlugin without it.

Validation

  • 516 engine tests in 86 suites on a clean build (Render, Scene, Sprite, Transform, ECS and the AdaScript sprite/particle/camera/navigation suites).
  • GPU (Metal, opt-in env vars, commands in the docs): 9 tests: animated frames and Aseprite regions in instanced and batched paths; a followed sprite staying centred in the frame it moved, zoom spacing, limits, shake; pixel-perfect picture position/border at two output sizes, hard-edged art pixels, fit mode, an ordinary camera unchanged, and UI blocks on exact output pixels including over the border. The pixel-perfect tests run the whole engine (camera extraction, target preparation, 2D graph with the UI plugin, upscale node).
  • 21 Editor tests pass (Sprite Animation editor, Camera 2D and camera settings, and the neighbouring Particle FX and Sprite Layout suites).

Not covered

Studio preview viewport and play window on a real GPU, WebGPU/browser, mobile, Windows. Cameras with a parent are unsupported for the controller (documented). Culling still uses the camera from the start of the frame. Pixel-perfect with real UI text/gradients and the glass effect was not drawn through the new path (the UI test uses an injected render item).

Reviewer notes

  • AdaUITests aborts with Value WindowFrameRequests is not stored in world both here and on the base commit (2855be92, verified in a separate copy), so it is not caused by this PR and could not be used as a regression check.
  • The Editor does not build against the pinned AdaMCP v0.2.0: EditorAgentWorkspaceMCPTools.swift uses _meta/Metadata, which that tag lacks. I verified the Editor in a scratch copy with that argument removed; the repository file is untouched by this PR.
  • A hash-layout Aseprite export is ordered by the number in frame names; export the array layout when in doubt.
  • Changing Camera's layout makes incremental SwiftPM builds with older objects crash (stale AdaSprite/test objects; a clean build is fine).

🤖 Generated with Claude Code

SpectralDragon and others added 5 commits October 19, 2026 18:03
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…and runtime checks

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…nd docs

Also stops EditorSceneViewportView.uiProjectRoot from looping forever when no ancestor holds a project marker.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…e view; fix multi-camera CameraSystem

CameraSystem inserted a camera's first GlobalViewUniform while iterating, which skipped cameras when several existed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ull-resolution UI

Camera.pixelPerfect renders at a fixed resolution and presents with nearest sampling. UI is drawn onto the scaled picture at output resolution. Studio Camera settings, picking and input mapping included.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@SpectralDragon SpectralDragon changed the title 2D: sprite animation (Aseprite, Studio, AdaScript) and Camera2D controller 2D: sprite animation, Camera2D controller and pixel-perfect rendering Oct 19, 2026
@SpectralDragon
SpectralDragon marked this pull request as ready for review October 19, 2026 22:10
@SpectralDragon
SpectralDragon merged commit e4db1f4 into main Oct 19, 2026
1 of 3 checks passed
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T22:11:24.029652Z 9b63493 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant