melhorando a leitura de projetos no mmpCreator
Deploy / Deploy (push) Successful in 3m12s Details

This commit is contained in:
JotaChina 2025-12-23 19:30:19 -03:00
parent 9cf3c585fe
commit a6291ef60a
7 changed files with 386967 additions and 370721 deletions

756121
_data/all.yml

File diff suppressed because it is too large Load Diff

View File

@ -86,6 +86,7 @@
- remixtrap-n.wav - remixtrap-n.wav
- screams.wav - screams.wav
- sect02.wav - sect02.wav
- sipaus2.wav
- synthpop-xcalibur-retrospect.wav - synthpop-xcalibur-retrospect.wav
- the-riddle-amandyte.wav - the-riddle-amandyte.wav
- titulo-incorreto-1.wav - titulo-incorreto-1.wav

1393
_data/sipaus2.yml Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -267,61 +267,67 @@ export async function parseMmpContent(xmlString) {
// 3. EXTRAÇÃO DAS TRILHAS DE BASSLINE E SEUS FILHOS // 3. EXTRAÇÃO DAS TRILHAS DE BASSLINE E SEUS FILHOS
// ------------------------------------------------------------- // -------------------------------------------------------------
let allBasslineInstruments = []; // -------------------------------------------------------------
// 3. EXTRAÇÃO DAS TRILHAS DE BASSLINE E DO RACK COMPARTILHADO
// -------------------------------------------------------------
const basslineContainers = bbTrackNodes // 3.1) Acha o "rack" que realmente contém os instrumentos do Beat/Bassline Editor
.map((trackNode) => { const bbRackNode = bbTrackNodes.find((n) =>
const trackName = trackNode.getAttribute("name") || "Beat/Bassline"; n.querySelector('bbtrack > trackcontainer > track[type="0"]')
const containerId = `bassline_${Date.now()}_${Math.random() );
.toString(36)
.substr(2, 9)}`;
// A. Extrai os clipes da timeline (blocos azuis) // Cria um ID único para o rack
const playlistClips = Array.from( const rackId = bbRackNode
trackNode.querySelectorAll(":scope > bbtco") ? `bbRack_${Date.now()}_${Math.random().toString(36).slice(2)}`
).map((bbtco) => { : null;
return {
pos: parseInt(bbtco.getAttribute("pos"), 10) || 0,
len: parseInt(bbtco.getAttribute("len"), 10) || 192,
name: trackName,
};
});
// Se não tiver clipes, geralmente é container vazio, mas vamos criar mesmo assim // 3.2) Parseia instrumentos UMA vez (do rack)
if (playlistClips.length === 0) return null; let bbRackInstruments = [];
if (bbRackNode && rackId) {
const internalInstrumentNodes = Array.from(
bbRackNode.querySelectorAll('bbtrack > trackcontainer > track[type="0"]')
);
// B. Extrai os instrumentos INTERNOS desta Bassline bbRackInstruments = internalInstrumentNodes
const internalInstrumentNodes = Array.from( .map((node) => parseInstrumentNode(node, sortedBBTrackNameNodes, pathMap, rackId))
trackNode.querySelectorAll('bbtrack > trackcontainer > track[type="0"]') .filter(Boolean);
); }
const internalInstruments = internalInstrumentNodes // 3.3) Agora cria os BBTracks (Caixa, Kick, etc) como "containers/patterns"
.map((node) => // Eles não carregam instrumentos próprios: só apontam para o rack.
parseInstrumentNode( const basslineContainers = bbTrackNodes
node, .map((trackNode, idx) => {
sortedBBTrackNameNodes, const trackName = trackNode.getAttribute("name") || "Beat/Bassline";
pathMap,
containerId
)
) // Passa ID do Pai
.filter((t) => t !== null);
// Acumula na lista geral de instrumentos const playlistClips = Array.from(
allBasslineInstruments.push(...internalInstruments); trackNode.querySelectorAll(":scope > bbtco")
).map((bbtco) => ({
pos: parseInt(bbtco.getAttribute("pos"), 10) || 0,
len: parseInt(bbtco.getAttribute("len"), 10) || 192,
name: trackName,
}));
return { if (playlistClips.length === 0) return null;
id: containerId,
name: trackName, return {
type: "bassline", // Tipo especial para o audio_ui.js id: `bassline_${Date.now()}_${Math.random().toString(36).slice(2)}`,
playlist_clips: playlistClips, name: trackName,
instruments: internalInstruments, // Mantém referência type: "bassline",
volume: 1, playlist_clips: playlistClips,
pan: 0,
patterns: [], // qual "pattern/coluna" este BBTrack representa
isMuted: trackNode.getAttribute("muted") === "1", patternIndex: idx,
};
}) // aponta pro rack real (se não achou rack, cai nele mesmo)
.filter((t) => t !== null); instrumentSourceId: rackId,
volume: 1,
pan: 0,
patterns: [],
isMuted: trackNode.getAttribute("muted") === "1",
};
})
.filter(Boolean);
// ------------------------------------------------------------- // -------------------------------------------------------------
// 4. COMBINAÇÃO E FINALIZAÇÃO // 4. COMBINAÇÃO E FINALIZAÇÃO

View File

@ -631,17 +631,25 @@ document.addEventListener("DOMContentLoaded", () => {
// --- FUNÇÕES GLOBAIS DE FOCO NO PATTERN --- // --- FUNÇÕES GLOBAIS DE FOCO NO PATTERN ---
window.openPatternEditor = function(basslineTrack) { window.openPatternEditor = function (basslineTrack) {
console.log("Focando na Bassline:", basslineTrack.name); console.log("Focando na Bassline:", basslineTrack.name);
// Define o ID da bassline como foco
appState.pattern.focusedBasslineId = basslineTrack.id; appState.pattern.focusedBasslineId = basslineTrack.id;
// Renderiza o editor, que agora vai filtrar e mostrar só o conteúdo dela
renderAll(); // 🔥 chave: sincroniza a coluna/pattern com o BBTrack escolhido
if (Number.isInteger(basslineTrack.patternIndex)) {
// Feedback visual opcional appState.pattern.activePatternIndex = basslineTrack.patternIndex;
showToast(`Editando: ${basslineTrack.name}`, "info");
// opcional: manter o selector UI consistente (se existir)
const sel = document.getElementById("global-pattern-selector");
if (sel) sel.value = String(basslineTrack.patternIndex);
} }
renderAll();
showToast(`Editando: ${basslineTrack.name}`, "info");
};
window.exitPatternFocus = function() { window.exitPatternFocus = function() {
console.log("Saindo do foco da Bassline"); console.log("Saindo do foco da Bassline");
appState.pattern.focusedBasslineId = null; appState.pattern.focusedBasslineId = null;

View File

@ -19,14 +19,24 @@ export function renderPatternEditor() {
let contextName = "Song Editor"; // Nome da visualização atual let contextName = "Song Editor"; // Nome da visualização atual
if (appState.pattern.focusedBasslineId) { if (appState.pattern.focusedBasslineId) {
isFocusedMode = true; isFocusedMode = true;
// Mostra apenas os filhos da Bassline selecionada
tracksToRender = appState.pattern.tracks.filter(t => t.parentBasslineId === appState.pattern.focusedBasslineId); // 1) acha o container (Caixa/Kick/...) focado
const basslineTrack = appState.pattern.tracks.find(
// Busca o nome para exibir no título t => t.id === appState.pattern.focusedBasslineId && t.type === "bassline"
const basslineTrack = appState.pattern.tracks.find(t => t.id === appState.pattern.focusedBasslineId); );
if (basslineTrack) contextName = basslineTrack.name;
} else { // 2) usa o rack real como "pai" (fallback: id do próprio container)
const srcId = basslineTrack?.instrumentSourceId || appState.pattern.focusedBasslineId;
// 3) mostra somente instrumentos pertencentes ao rack
tracksToRender = appState.pattern.tracks.filter(
t => t.type !== "bassline" && t.parentBasslineId === srcId
);
// Nome no header
if (basslineTrack) contextName = basslineTrack.name;
} else {
// Modo Padrão: Mostra trilhas da raiz (sem pai) e que NÃO são containers de bassline // Modo Padrão: Mostra trilhas da raiz (sem pai) e que NÃO são containers de bassline
tracksToRender = appState.pattern.tracks.filter(t => t.type !== 'bassline' && t.parentBasslineId === null); tracksToRender = appState.pattern.tracks.filter(t => t.type !== 'bassline' && t.parentBasslineId === null);
@ -170,7 +180,11 @@ export function redrawSequencer() {
if (!trackData || !trackData.patterns || trackData.patterns.length === 0) return; if (!trackData || !trackData.patterns || trackData.patterns.length === 0) return;
const activePatternIndex = trackData.activePatternIndex || 0; const isFocused = !!appState.pattern.focusedBasslineId;
const activePatternIndex = isFocused
? (appState.pattern.activePatternIndex || 0)
: (trackData.activePatternIndex || 0);
const activePattern = trackData.patterns[activePatternIndex]; const activePattern = trackData.patterns[activePatternIndex];
if (!activePattern) return; if (!activePattern) return;
@ -299,7 +313,10 @@ export function updateGlobalPatternSelector() {
const activeTrack = appState.pattern.tracks.find(t => t.id === activeTrackId); const activeTrack = appState.pattern.tracks.find(t => t.id === activeTrackId);
// Tenta pegar a track ativa ou a primeira visível como referência de patterns // Tenta pegar a track ativa ou a primeira visível como referência de patterns
const referenceTrack = activeTrack || appState.pattern.tracks.find(t => !t.isMuted && t.type !== 'bassline'); const isFocused = !!appState.pattern.focusedBasslineId;
const referenceTrack = isFocused
? appState.pattern.tracks.find(t => t.type !== "bassline" && t.parentBasslineId !== null)
: (activeTrack || appState.pattern.tracks.find(t => !t.isMuted && t.type !== "bassline"));
globalPatternSelector.innerHTML = ''; globalPatternSelector.innerHTML = '';
@ -311,10 +328,12 @@ export function updateGlobalPatternSelector() {
globalPatternSelector.appendChild(option); globalPatternSelector.appendChild(option);
}); });
if (activeTrack) { if (isFocused) {
globalPatternSelector.value = activeTrack.activePatternIndex || 0; globalPatternSelector.value = appState.pattern.activePatternIndex || 0;
} else if (activeTrack) {
globalPatternSelector.value = activeTrack.activePatternIndex || 0;
} else { } else {
globalPatternSelector.value = 0; globalPatternSelector.value = 0;
} }
globalPatternSelector.disabled = false; globalPatternSelector.disabled = false;
} else { } else {