criação de novas patterns de composição nos projetos

This commit is contained in:
JotaChina committed 2025-12-27 18:32:06 -03:00
1 parent df0708adf3
commit f80d6511a4
3 files changed
+144 -12

No files matched your search

+44 -12
View File
@@ -553,20 +553,17 @@ export async function parseMmpContent(xmlString) {
name: trackName,
}));
if (playlistClips.length === 0) return null;
// ❌ remove esta linha:
// if (playlistClips.length === 0) return null;
// ✅ mantém mesmo vazia
return {
id: `bassline_${Date.now()}_${Math.random().toString(36).slice(2)}`,
name: trackName,
type: "bassline",
playlist_clips: playlistClips,
// 🔥 importante: qual “coluna/pattern” este BBTrack representa
playlist_clips: playlistClips, // pode ser []
patternIndex: idx,
// 🔥 importante: de onde vêm os instrumentos
instrumentSourceId: rackId,
volume: 1,
pan: 0,
patterns: [],
@@ -575,6 +572,7 @@ export async function parseMmpContent(xmlString) {
})
.filter(Boolean);
// -------------------------------------------------------------
// 4. COMBINAÇÃO E FINALIZAÇÃO
// -------------------------------------------------------------
@@ -744,27 +742,60 @@ export function syncPatternStateToServer() {
const currentXml = generateXmlFromState();
sendAction({ type: "SYNC_PATTERN_STATE", xml: currentXml });
saveStateToSession();
function ensureBbTrackCount(xmlDoc, neededCount) {
const songTc = xmlDoc.querySelector("song > trackcontainer");
if (!songTc) return;
let bbTracks = Array.from(songTc.querySelectorAll(':scope > track[type="1"]'));
if (bbTracks.length === 0) return;
const template = bbTracks[bbTracks.length - 1];
while (bbTracks.length < neededCount) {
const clone = template.cloneNode(true);
// limpa blocos
Array.from(clone.querySelectorAll(":scope > bbtco")).forEach((n) => n.remove());
// deixa o container interno “limpo” (opcional)
const inner = clone.querySelector('bbtrack > trackcontainer');
if (inner) inner.querySelectorAll('track[type="0"]').forEach((n) => n.remove());
// nome default
clone.setAttribute("name", `Beat/Bassline ${bbTracks.length}`);
songTc.appendChild(clone);
bbTracks.push(clone);
}
}
}
function applyPlaylistClipsToXml(xmlDoc) {
const bbTrackNodes = Array.from(xmlDoc.querySelectorAll('track[type="1"]'));
if (!bbTrackNodes.length) return;
const basslines = appState.pattern.tracks
.filter((t) => t.type === "bassline" && Number.isFinite(Number(t.patternIndex)))
.slice()
.sort((a, b) => Number(a.patternIndex) - Number(b.patternIndex));
const maxIdx = Math.max(-1, ...basslines.map((b) => Number(b.patternIndex)));
ensureBbTrackCount(xmlDoc, maxIdx + 1);
const bbTrackNodes = Array.from(xmlDoc.querySelectorAll('track[type="1"]'));
if (!bbTrackNodes.length) return;
for (const b of basslines) {
const idx = Number(b.patternIndex);
const node = bbTrackNodes[idx];
if (!node) continue;
// remove bbtco existentes
// ✅ mantém nome/mute sincronizados
if (b.name) node.setAttribute("name", b.name);
node.setAttribute("muted", b.isMuted ? "1" : "0");
Array.from(node.querySelectorAll(":scope > bbtco")).forEach((n) => n.remove());
const clips = (b.playlist_clips || []).slice().sort((x, y) => (x.pos ?? 0) - (y.pos ?? 0));
for (const c of clips) {
const el = xmlDoc.createElement("bbtco");
el.setAttribute("pos", String(Math.max(0, Math.floor(c.pos ?? 0))));
@@ -774,6 +805,7 @@ function applyPlaylistClipsToXml(xmlDoc) {
}
}
function createTrackXml(track) {
if (!track.patterns || track.patterns.length === 0) return "";