Skip to content

extend matrix field to support editing sprites - #18

Open
IanMatthewHuff wants to merge 1 commit into
base/pr-11296-11c03ac-run-20260508T194836Zfrom
review/pr-11296-343455c-run-20260508T194836Z-copilot
Open

extend matrix field to support editing sprites#18
IanMatthewHuff wants to merge 1 commit into
base/pr-11296-11c03ac-run-20260508T194836Zfrom
review/pr-11296-343455c-run-20260508T194836Z-copilot

Conversation

@IanMatthewHuff

Copy link
Copy Markdown
Owner

for a long time we've been toying around with the idea of having an "arcade junior" for lower grades. one problem we've always run into, however, is our asset editors. they have a few features that make it harder for younger students to use them:

  1. they're complicated with lots of features
  2. they open in a modal, which breaks context while editing programs
  3. the previews they show are tiny so they don't show up well in printed materials/screenshots
  4. keyboard navigation is complicated

fast forward to last week, where someone sent me a link to the diversibit which got me thinking about how hard it would be to take the matrix field editor that we use in micro:bit and make a version of it for a grid of neopixels, and i realized this would be a great way to kill two birds with one stone!

the matrix field pretty much solves all the arcade junior issues:

  1. it's way simpler
  2. it's inline in the code
  3. the matrix is nice and big on the block
  4. it already supports keyboard navigation

with the obvious downside that you can't resize the sprite, but that's probably a good restriction for arcade junior anyhow.

this PR takes our LED matrix field and adds optional support for color, plus some parameters that let you customize the appearance to make it more amenable to pixel grids (removing the corner radius, spacing between cells, etc.). the way the color switching works is through a second field which gets added before the matrix field on the block; this field just pops up a menu of color options that change the "on" color of the matrix. all the other keyboard/mouse interactions are the same: clicking a "lit" cell turns it off and clicking an "unlit" cell turns it on with the selected color.

as for the palette of colors, you can either take the project palette (for arcade) or specify the colors using a comment attribute (for diversibit/other neopixel grids). i briefly considered just using the project palette for the other case too, but realized that it might end up conflicting with the palette used by the display shield.

here's me messing around with keyboard controls:

inline-sprites

i'm probably going to have a follow up pr that adds support for tagged template literals with the field (right now it's always strings). i'm still trying to figure out how exactly to have the decompilation for that coexist with the regular image editor


Mirrored from upstream PR: https://​github.com/microsoft/pxt/pull/11296
Created automatically by pxt-review-ops for code-review agent comparison.
(URL wrapped in a code span so GitHub does not create a cross-reference on the upstream timeline.)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the existing LED matrix (grid literal) Blockly field to optionally support color-based editing (intended for inline sprite/pixel-grid editing), including configurable palette sources and visual tuning options (spacing, border radius).

Changes:

  • Adds new comment attributes / typings to enable colorGridLiteral, palette selection, and grid appearance customization.
  • Updates decompilation/compilation paths to preserve and round-trip a broader character set for grid/image literals.
  • Enhances the Blockly field implementation to store per-cell color indices and introduces an inline color picker field.
Show a summary per file
File Description
pxtlib/service.ts Registers new comment attributes for color grid literals and appearance tuning.
pxtcompiler/emitter/decompiler.ts Decompiles colorGridLiteral image patterns into block field state.
pxtblocks/loader.ts Wires new palette options + optional inline color picker into grid-literal blocks.
pxtblocks/fields/field_tileset.ts Exports transparency-tile image helper for reuse in color picker UI.
pxtblocks/fields/field_matrix.ts Allows 0 border radius (square cells) by permitting rx=0.
pxtblocks/fields/field_ledmatrix.ts Switches matrix state to numeric indices, adds palette support, and serializes with an extended alphabet.
pxtblocks/fields/field_ledmatrix_colorPicker.ts Introduces a dropdown color picker field to drive the active “on” color.
pxtblocks/compiler/environment.ts Treats colorGridLiteral as an image-literal-bearing block for compilation.
pxtblocks/compiler/compiler.ts Emits image/grid literal strings without normalizing to .# only.
localtypings/pxtarget.d.ts Adds/organizes new target attribute typings for the enhanced grid literal field.

Copilot's findings

  • Files reviewed: 9/10 changed files
  • Comments generated: 10

Comment on lines +48 to +55
export class FieldLEDMatrixColorPicker extends FieldImageDropdown {
constructor(blocksInfo: pxtc.BlocksInfo, colors?: string[], colorNames?: string[], protected includeTransparency = false) {
super((colors || DEFAULT_LED_COLORS)[0], {
blocksInfo,
columns: "4",
data: generateOptions(colors, colorNames, includeTransparency)
});
}

onColorSelected(index: number) {
if (!this.sourceBlock_) return;
const field = this.sourceBlock_.getField("LEDS") as FieldLedMatrix;
Comment on lines +98 to 107
if (this.params.hasOffColor) {
this.offOpacity = 1.0;
}

if (this.params.offColor !== undefined) {
this.offColor = this.params.offColor;
if (this.params.offOpacity) {
const val = parseFloat(this.params.offOpacity);
if (!isNaN(val) && val >= 0 && val <= 1) {
this.offOpacity = val;
}
}
Comment on lines +88 to +96
if (this.params.colorNames) {
this.colorNames = this.params.colorNames;
}
else {
this.colorNames = [
lf("off"),
...DEFAULT_LED_COLORS
];
}
const val = parseCharacter(row[j]);

if (val !== -1) {
this.cellState[x][y] = val;
Comment on lines +444 to +457
function parseCharacter(c: string): number {
const chars = ".#23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
switch (c) {
case "#":
case "*":
case "1":
return 1;
case ".":
case "_":
case "0":
return 0;
default:
return chars.indexOf(c.toUpperCase());
}
Comment on lines 420 to 429
// Composes the state into a string an updates the field's state
private updateValue() {
const chars = ".#23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let res = "";
for (let y = 0; y < this.numMatrixRows; y++) {
for (let x = 0; x < this.numMatrixCols; x++) {
res += (this.cellState[x][y] ? "#" : ".") + " "
res += chars.charAt(this.cellState[x][y]) + " ";
}
res += "\n" + FieldLedMatrix.TAB
res += "\n" + FieldLedMatrix.TAB;
}
Comment thread pxtblocks/loader.ts
Comment on lines +335 to +338
if (fn.attributes.gridLiteralUseProjectPalette) {
colors = pxt.appTarget.runtime.palette!;
colorNames = colors.map((c, i) => i === 0 ? lf("{id:color}transparency") : pxt.U.lf("{id:color}color {0}", i));
}
if (j > 0)
state += ' ';
state += (leds[(i * columns) + j] === '#') ? "#" : ".";
state += leds[(i * columns) + j];
case ".":
case "_":
case "0":
return 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pxt-review-ops/comparison-pr Mirrored review PR created by pxt-review-ops

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants