feat: add bar width multiplier (1x–8x horizontal zoom) for track grid

This commit is contained in:
Xiaohan-Tian
2026-04-10 18:17:36 -07:00
parent 4917e54048
commit 139684b413
8 changed files with 153 additions and 9 deletions
+15 -2
View File
@@ -44,11 +44,15 @@ export class KGProject {
@WithDefault([0, 0])
private loopingRange: [number, number] = [0, 0]; // [startBar, endBar] - bar indices (0-based)
@Expose()
@WithDefault(1)
private barWidthMultiplier: number = 1;
@Expose()
@WithDefault(0)
private projectStructureVersion: number = 0;
public static readonly CURRENT_PROJECT_STRUCTURE_VERSION: number = 4;
public static readonly CURRENT_PROJECT_STRUCTURE_VERSION: number = 5;
@Expose()
@Type(() => KGTrack, {
@@ -64,7 +68,7 @@ export class KGProject {
private tracks: KGTrack[] = [];
// Constructor
constructor(name: string = "Untitled Project", maxBars: number = 32, currentBars: number = 0, bpm: number = 125, timeSignature: TimeSignature = { numerator: 4, denominator: 4 }, keySignature: KeySignature = "C major", selectedMode: string = "ionian", isLooping: boolean = false, loopingRange: [number, number] = [0, 0], tracks: KGTrack[] = [], projectStructureVersion: number = KGProject.CURRENT_PROJECT_STRUCTURE_VERSION) {
constructor(name: string = "Untitled Project", maxBars: number = 32, currentBars: number = 0, bpm: number = 125, timeSignature: TimeSignature = { numerator: 4, denominator: 4 }, keySignature: KeySignature = "C major", selectedMode: string = "ionian", isLooping: boolean = false, loopingRange: [number, number] = [0, 0], barWidthMultiplier: number = 1, tracks: KGTrack[] = [], projectStructureVersion: number = KGProject.CURRENT_PROJECT_STRUCTURE_VERSION) {
this.name = name;
this.maxBars = maxBars;
this.currentBars = currentBars;
@@ -74,6 +78,7 @@ export class KGProject {
this.selectedMode = selectedMode;
this.isLooping = isLooping;
this.loopingRange = loopingRange;
this.barWidthMultiplier = barWidthMultiplier;
this.tracks = tracks;
this.projectStructureVersion = projectStructureVersion;
}
@@ -167,5 +172,13 @@ export class KGProject {
public setLoopingRange(loopingRange: [number, number]): void {
this.loopingRange = loopingRange;
}
public getBarWidthMultiplier(): number {
return this.barWidthMultiplier;
}
public setBarWidthMultiplier(barWidthMultiplier: number): void {
this.barWidthMultiplier = barWidthMultiplier;
}
}
@@ -3,6 +3,7 @@ import { upgradeToV1 } from './upgradeToV1';
import { upgradeToV2 } from './upgradeToV2';
import { upgradeToV3 } from './upgradeToV3';
import { upgradeToV4 } from './upgradeToV4';
import { upgradeToV5 } from './upgradeToV5';
/**
* Upgrade the given project to the latest structure version, one version at a time.
@@ -38,6 +39,10 @@ export function upgradeProjectToLatest(project: KGProject): KGProject {
workingProject = upgradeToV4(workingProject);
break;
}
case 5: {
workingProject = upgradeToV5(workingProject);
break;
}
default: {
// If an upgrader is missing, throw to prevent loading incompatible structures
throw new Error(`No upgrader found for project structure version ${nextVersion}`);
+13
View File
@@ -0,0 +1,13 @@
import { KGProject } from '../KGProject';
export function upgradeToV5(project: KGProject): KGProject {
try {
const current = project.getBarWidthMultiplier?.();
if (current === undefined || current === null) {
project.setBarWidthMultiplier(1);
}
} finally {
project.setProjectStructureVersion(5);
}
return project;
}