The active tilemap layer can be renamed from the painting section, and a Show setting fades or hides the other layers in the scene view while the tilemap is selected (#138)
game-maker / gate (push) Successful in 1m40s
game-maker / suite (push) Successful in 6m4s

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5 committed 2026-09-18 10:56:32 +02:00
1 parent bfbcbe604c
commit f53279d065
10 files changed
+248 -13

No files matched your search

+107 -1
View File
@@ -64,8 +64,31 @@ async function cellShows(t, x, y, quadrants) {
return { ok: off.length === 0, detail: JSON.stringify({ read, want }) };
}
/** `over` laid at `alpha` on `under`, both `#rrggbb` as `pixelAt` reads them. */
function blend(over, under, alpha) {
const channel = (hex, i) => parseInt(hex.slice(i, i + 2), 16);
return `#${[1, 3, 5]
.map((i) => Math.round(channel(over, i) * alpha + channel(under, i) * (1 - alpha)))
.map((c) => c.toString(16).padStart(2, '0'))
.join('')}`;
}
export async function tilemap(t) {
const { check, json, evaluate, mutate, click, clickText, drag, press, shot, settle, undo, select } = t;
const {
check,
json,
evaluate,
mutate,
click,
clickText,
drag,
press,
typeText,
shot,
settle,
undo,
select,
} = t;
const { saved, api, navigate, projectId } = t;
await press('Escape');
@@ -283,6 +306,89 @@ export async function tilemap(t) {
await undo();
await settle();
// 40m. The painted layer is named in the field below the list, and Show singles it out in the
// scene view (#138). It sits here, not at the end, because here both layers exist: the upper
// one is painted on and holds the cell (4,0), the lower one the 3 × 3 block.
const nameField = await inInspector(t, '__gm.tilemap.layerNameAt()');
if (nameField) {
await click(nameField.x, nameField.y);
await press('a', { ctrl: true });
await typeText('Roofs');
await press('Enter');
}
await settle();
layers = await json(`__gm.tilemap.layers(${JSON.stringify(made.id)})`);
const renamedRow = await json('(__gm.tilemap.layerRowAt(0) || {}).id');
const nameNow = await json('(__gm.tilemap.layerNameAt() || {}).value');
check(
'the name field renames the layer painted on, and the list shows the new name',
layers[1].name === 'Roofs' &&
layers[0].name === 'Layer 1' &&
renamedRow === layers[1].id &&
nameNow === 'Roofs',
JSON.stringify({ layers, renamedRow, nameNow }),
);
// Pixels again, so the animation is cut down to one step for the reading, as in 40e.
await mutate("__gm.state.project.assets.find((a) => a.id === 'at-grass').pictures = ['at-floor-1']");
await settle();
const quarter = async (x, y) => (await cellQuarters(t, x, y))?.[0] ?? null;
const lowerWhole = await quarter(1, 1);
const emptyCell = await quarter(5, 3);
const upperWhole = await quarter(4, 0);
/** Chooses an entry of the Show dropdown: the topmost hit, which is the open menu. */
const show = async (label) => {
const button = await inInspector(t, '__gm.tilemap.focusAt()');
if (button) await click(button.x, button.y);
await settle();
const entry = await t.locate(label, true);
await click(entry.x, entry.y);
await settle();
};
await show('Others faded');
const faded = await quarter(1, 1);
// The lower layer is laid over the background at 30 %, so its colour lands in between.
const mix = lowerWhole && emptyCell && blend(lowerWhole, emptyCell, 0.3);
const focusLabel = await json('(__gm.tilemap.focusAt() || {}).label');
check(
'Others faded draws the other layers at 30 % and the painted one whole',
Boolean(mix) &&
colourDistance(faded, mix) <= 16 &&
colourDistance(await quarter(4, 0), upperWhole) <= 12 &&
focusLabel === 'Others faded',
JSON.stringify({ faded, mix, lowerWhole, emptyCell, focusLabel }),
);
await show('Active layer only');
const solo = await quarter(1, 1);
const soloInfo = await json(`__gm.tilemap.info(${JSON.stringify(MAP_OBJECT)})`);
check(
'Active layer only leaves the other layers out and keeps the painted one',
colourDistance(solo, emptyCell) <= 12 &&
colourDistance(await quarter(4, 0), upperWhole) <= 12 &&
soloInfo.drawCalls === 1,
JSON.stringify({ solo, emptyCell, soloInfo }),
);
// Only the selected map is singled out; deselected it is drawn whole, and the model never changed.
await evaluate('__gm.state.select(null)');
await settle();
const deselected = await quarter(1, 1);
layers = await json(`__gm.tilemap.layers(${JSON.stringify(made.id)})`);
check(
'a deselected map is drawn whole again, and Show hid nothing in the model',
colourDistance(deselected, lowerWhole) <= 12 && layers.every((l) => !l.hidden),
JSON.stringify({ deselected, lowerWhole, layers }),
);
await select({ kind: 'object', holderId: 'scene1', objectIds: [MAP_OBJECT], objectId: MAP_OBJECT });
await show('All layers');
await mutate(
"__gm.state.project.assets.find((a) => a.id === 'at-grass').pictures = ['at-floor-1', 'at-floor-2']",
);
await undo(); // the rename
await settle();
// 40i. Back to Select: the map is moved again instead of painted on.
await clickInInspector(t, '__gm.tilemap.toolAt("select")');
await settle();