fix: correct draw_pixels placement when cel is not at origin (0,0)#20
Open
hansonchris wants to merge 1 commit into
Open
fix: correct draw_pixels placement when cel is not at origin (0,0)#20hansonchris wants to merge 1 commit into
hansonchris wants to merge 1 commit into
Conversation
draw_pixels wrote to cel.image via Image:putPixel using sprite coordinates, but putPixel expects cel-LOCAL coordinates. Once a layer's cel is trimmed to a non-(0,0) origin (e.g. after a shape tool runs), every pixel was offset by the cel's position, and pixels falling outside the cel's bounds were dropped entirely. The shape tools are unaffected because they use app.useTool, which operates in sprite space. Normalize the target cel to a full-canvas image at (0,0) before writing (compositing any existing content first), so sprite coordinates equal image coordinates. This also gives a freshly created cel a valid image, fixing draw_pixels on newly added layers. Aseprite re-trims the cel on save, so canvas dimensions and file size are unchanged. Tests: - pkg/aseprite/lua_test.go: unit assertion that the generated script normalizes the cel to full-canvas at (0,0). Runs without Aseprite, so it guards the fix in CI, where the integration tests do not run. - pkg/tools: integration tests for the offset-after-shape case and for an asymmetric cel origin with a pixel outside the shape's bounds (the lost-pixel case). Both fail on stock and pass with this change.
Fuitad
added a commit
to Fuitad/pixel-plugin
that referenced
this pull request
Jul 2, 2026
Refreshes all 5 platform binaries from Fuitad/pixel-mcp @ 0fdedc5 (based on upstream v0.5.0), which includes two fixes not yet released upstream: - Indexed palette transparentColor collision: Palette:resize silently clamped Sprite.transparentColor into the resized palette's valid index range, colliding it with a real color (typically the palette's last entry). Once collided, "transparent" fills wrote that real color's index, and pixels drawn in that color could be auto-trimmed away as if transparent. - draw_pixels cel-origin bug (willibrandon/pixel-mcp#20): draw_pixels wrote via Image:putPixel using sprite coordinates, but putPixel expects cel-local coordinates, so pixels were offset or dropped whenever a cel had been trimmed to a non-(0,0) origin (e.g. after any shape tool ran). Bumps plugin version to 0.5.1 and documents the change in CHANGELOG.md.
This was referenced Jul 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #19.
Problem
draw_pixelswrote tocel.imageviaImage:putPixelusing sprite coordinates, butputPixelexpects cel-local coordinates. Once a layer's cel is trimmed to a non-(0,0) origin (e.g. after any shape tool runs), every pixel was offset by the cel's position, and pixels outside the cel bounds were dropped. The shape tools are unaffected because they useapp.useTool, which works in sprite space.draw_pixelson a newly added layer could also hit a nil cel image (spr:newCel2-arg form).Fix
Normalize the target cel to a full-canvas image at (0,0) before writing (compositing any existing content first), so sprite coordinates equal image coordinates. This also gives a fresh cel a valid image. Aseprite re-trims the cel on save, so canvas dimensions and file size are unchanged.
Tests
TestLuaGenerator_DrawPixels_NormalizesCel(unit,pkg/aseprite/lua_test.go) — asserts the generated script normalizes the cel to full-canvas at (0,0). Runs without Aseprite, so it guards the fix in CI (the integration tests require a real Aseprite install).TestIntegration_DrawPixels_AfterShape_CelOffset— circle, then a pixel at (16,16); asserts it lands exactly there.TestIntegration_DrawPixels_AfterShape_OutsideShapeBounds— asymmetric cel origin plus a pixel outside the shape's bbox (the lost-pixel case).All three fail on
mainand pass with this change.Verification
Notes
In indexed mode a new
Imageis filled with index 0 (the default transparent index), so transparency is preserved in the common case; if a sprite has a non-defaultspr.transparentColor, that should be honored — flagging in case you'd like a follow-up.