2026-07-13 04:39:10 +02:00
|
|
|
import * as Sentry from '@sentry/react';
|
|
|
|
|
import { Note, Pad, ProjectRawData } from '../../types/types';
|
|
|
|
|
import { getSampleName } from '../exporters/utils';
|
|
|
|
|
import { noteNumberToName } from '../parsers';
|
|
|
|
|
import { findPad, findSoundByPad, findSoundIdByPad } from '../utils';
|
|
|
|
|
|
|
|
|
|
export type ViewNote = Note & { name: string };
|
|
|
|
|
|
|
|
|
|
export type ViewPattern = {
|
|
|
|
|
pad: string;
|
|
|
|
|
bars: number;
|
|
|
|
|
soundName: string;
|
|
|
|
|
notes: ViewNote[];
|
|
|
|
|
group: string;
|
|
|
|
|
padNumber: number;
|
|
|
|
|
midiChannel: number;
|
|
|
|
|
soundId: number;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export type ViewScene = {
|
|
|
|
|
name: string;
|
|
|
|
|
patterns: ViewPattern[];
|
|
|
|
|
maxBars: number;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export type ViewPad = Pad;
|
|
|
|
|
|
|
|
|
|
export type ViewData = {
|
|
|
|
|
pads: Record<string, ViewPad[]>;
|
|
|
|
|
scenes: ViewScene[];
|
|
|
|
|
scenesSettings: ProjectRawData['scenesSettings'];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function webViewTransformer(data: ProjectRawData): ViewData {
|
|
|
|
|
const { pads, scenes } = data;
|
|
|
|
|
const newScenes: ViewScene[] = [];
|
|
|
|
|
const usedPads = new Set<string>();
|
|
|
|
|
|
|
|
|
|
if (import.meta.env.DEV) {
|
|
|
|
|
console.log(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// construct new scenes array
|
|
|
|
|
// and collect the used pads
|
|
|
|
|
scenes.forEach((scene, idx) => {
|
|
|
|
|
newScenes[idx] = {
|
|
|
|
|
name: scene.name,
|
2026-07-14 09:44:50 +02:00
|
|
|
maxBars: Math.max(
|
|
|
|
|
1,
|
|
|
|
|
...scene.patterns.map((pattern) => pattern.bars),
|
|
|
|
|
...Object.values(scene.patternEvents).map((pattern) => pattern?.bars || 0),
|
|
|
|
|
),
|
2026-07-13 04:39:10 +02:00
|
|
|
patterns: [],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (const pattern of scene.patterns) {
|
|
|
|
|
if (pattern.notes.length > 0) {
|
|
|
|
|
usedPads.add(pattern.pad);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// also add pads that have samples assigned (even without patterns)
|
|
|
|
|
for (const group in pads) {
|
2026-07-14 11:53:31 +02:00
|
|
|
pads[group].forEach((pad) => {
|
2026-07-13 04:39:10 +02:00
|
|
|
if (pad.soundId > 0) {
|
2026-07-14 11:53:31 +02:00
|
|
|
usedPads.add(`${group}${pad.pad - 1}`);
|
2026-07-13 04:39:10 +02:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newScenes.forEach((scene, idx) => {
|
|
|
|
|
// make sure each scene have the same tracks/pads
|
|
|
|
|
usedPads.forEach((pad) => {
|
|
|
|
|
const patternByPad = scene.patterns.find((p) => p.pad === pad);
|
|
|
|
|
if (!patternByPad) {
|
|
|
|
|
const group = pad[0];
|
|
|
|
|
const padNumber = parseInt(pad.slice(1), 10);
|
|
|
|
|
const soundId = findSoundIdByPad(pad, pads) || 0;
|
|
|
|
|
const sound = findSoundByPad(pad, pads, data.sounds);
|
|
|
|
|
const padObject = findPad(pad, pads);
|
|
|
|
|
|
|
|
|
|
scene.patterns.push({
|
|
|
|
|
pad,
|
|
|
|
|
notes: [],
|
|
|
|
|
bars: 0,
|
|
|
|
|
group,
|
|
|
|
|
padNumber,
|
|
|
|
|
soundName: getSampleName(sound?.meta?.name, soundId, false),
|
|
|
|
|
midiChannel: padObject?.midiChannel || 0,
|
|
|
|
|
soundId,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// copy notes to exiting patterns
|
|
|
|
|
scenes[idx].patterns.forEach((pattern) => {
|
|
|
|
|
const patternInScene = scene.patterns.find((p) => p.pad === pattern.pad);
|
|
|
|
|
if (!patternInScene) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
patternInScene.notes = pattern.notes
|
|
|
|
|
.map((note) => ({
|
|
|
|
|
...note,
|
|
|
|
|
name: noteNumberToName(note.note),
|
|
|
|
|
}))
|
|
|
|
|
.reduce((acc, note) => {
|
|
|
|
|
const existingNoteInThisPosition = acc.find((n) => n.position === note.position);
|
|
|
|
|
|
|
|
|
|
if (existingNoteInThisPosition) {
|
|
|
|
|
existingNoteInThisPosition.name = `${existingNoteInThisPosition.name},${note.name}`;
|
|
|
|
|
return acc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
acc.push({ ...note });
|
|
|
|
|
return acc;
|
|
|
|
|
}, [] as ViewNote[]);
|
|
|
|
|
patternInScene.bars = pattern.bars;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
scene.patterns.sort((a, b) =>
|
|
|
|
|
a.pad.localeCompare(b.pad, undefined, { numeric: true, sensitivity: 'base' }),
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sentry.setContext('webViewData', {
|
|
|
|
|
pads,
|
|
|
|
|
scenes: newScenes,
|
|
|
|
|
scenesSettings: data.scenesSettings,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
pads,
|
|
|
|
|
scenes: newScenes,
|
|
|
|
|
scenesSettings: data.scenesSettings,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default webViewTransformer;
|