Snap a new song to 1/16, and route new assets as the others (#365)
game-maker / gate (push) Successful in 4m3s
game-maker / suite (push) Failing after 14m40s

A new song snapped to whole bars, too coarse to lay out a beat. And a
new or duplicated sound, instrument, pattern or song went to the
master alone, so every one had to be linked into the buses by hand
again.

- A song without a grid of its own snaps to 1/16. The songs in the
  user's project have Bar written in and keep it.
- A new or duplicated sound, instrument, pattern or song gets the links
  of the one whose targets most others of its type share, at their
  volume. On a tie the latest of them decides, so a single song decides
  for the next one.
- Where nothing of its type is linked yet, it goes as most of all that
  plays, and where nothing is, to the master. A new bus still goes to
  the master alone.
- Assets made at once are matched against what stood before, not
  against each other. A project from before the routing still opens
  with everything on the master.
- The song tab has a gridAt hook. e2e 65 checks the new grid and sets
  Bar, which its checks go by.

Tests:

- Unit master-routing (1 new) and song (1 rewritten): 26 green. Counter
  checks (rule off, grid back to Bar) red.
- e2e 65 (melektaus-atx): ALL PASSED, 58 checks (1 new).
- Gate (melektaus-atx): CHECK EXIT 0, 273 files, 4226 tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-09 09:37:44 +02:00
1 parent 0e73fd85b9
commit f840ec3c44
7 files changed
+131 -11

No files matched your search

+5 -4
View File
@@ -3,6 +3,7 @@ import { CompoundCommand } from '../../core/commands/CompoundCommand';
import { nextAssetName } from '../../core/commands/naming';
import { SetSongCommand } from '../../core/commands/songCommands';
import {
DEFAULT_SONG_GRID,
newItem,
SONG_GRID_KEY,
SONG_GRID_OPTIONS,
@@ -79,7 +80,7 @@ interface Take {
export class SongEditor extends AssetTabEditor<SongAsset, SongTimeline> {
/** Public for the check scripts. */
readonly playButton: Button;
readonly gridButton = new Dropdown('Bar', { width: GRID_WIDTH });
readonly gridButton = new Dropdown(DEFAULT_SONG_GRID, { width: GRID_WIDTH });
readonly recordButton: Button;
readonly inputButton = new Dropdown('Default input', { width: INPUT_WIDTH });
readonly meter = new TakeMeter();
@@ -518,7 +519,7 @@ export class SongEditor extends AssetTabEditor<SongAsset, SongTimeline> {
private openGridMenu(): void {
const asset = this.asset();
if (!asset) return;
const current = textOf(asset.props[SONG_GRID_KEY] ?? 'bar');
const current = textOf(asset.props[SONG_GRID_KEY] ?? DEFAULT_SONG_GRID);
new Menu(
SONG_GRID_OPTIONS.map((option) => ({
label: option.label,
@@ -574,8 +575,8 @@ export class SongEditor extends AssetTabEditor<SongAsset, SongTimeline> {
this.fitButton.setEnabled(asset !== null);
this.syncViewButtons(asset);
this.syncPlayButton();
const grid = asset ? textOf(asset.props[SONG_GRID_KEY] ?? 'bar') : 'bar';
this.gridButton.setText(SONG_GRID_OPTIONS.find((o) => o.value === grid)?.label ?? 'Bar');
const grid = textOf(asset?.props[SONG_GRID_KEY] ?? DEFAULT_SONG_GRID);
this.gridButton.setText(SONG_GRID_OPTIONS.find((o) => o.value === grid)?.label ?? DEFAULT_SONG_GRID);
this.follow(asset);
}
}