melhorando a leitura de projetos no mmpCreator
Deploy / Deploy (push) Successful in 1m56s Details

This commit is contained in:
JotaChina 2025-12-22 18:34:49 -03:00
parent 3bd714e29d
commit 6beebe7ea2
2 changed files with 28 additions and 35 deletions

View File

@ -104,7 +104,7 @@ function parseInstrumentNode(
const trackName = trackNode.getAttribute("name"); const trackName = trackNode.getAttribute("name");
const instrumentName = instrumentNode.getAttribute("name"); const instrumentName = instrumentNode.getAttribute("name");
// 1. Coleta TODOS os patterns reais dentro do XML do instrumento // Lógica de Patterns
const allPatternsNodeList = trackNode.querySelectorAll("pattern"); const allPatternsNodeList = trackNode.querySelectorAll("pattern");
const allPatternsArray = Array.from(allPatternsNodeList).sort((a, b) => { const allPatternsArray = Array.from(allPatternsNodeList).sort((a, b) => {
return ( return (
@ -113,18 +113,14 @@ function parseInstrumentNode(
); );
}); });
// 2. CORREÇÃO PRINCIPAL: const patternsToCreate =
// O loop deve ser baseado nos patterns existentes no XML, não nos blocos da timeline (bbtco). sortedBBTrackNameNodes.length > 0
// Se não houver patterns no XML (instrumento vazio), criamos um array com 1 item para gerar o pattern default. ? sortedBBTrackNameNodes
const loopSource = allPatternsArray.length > 0 ? allPatternsArray : [null]; : [{ getAttribute: () => "Pattern 1" }];
const patterns = loopSource.map((patternNode, index) => { const patterns = patternsToCreate.map((bbTrack, index) => {
// Tenta pegar o nome do bloco correspondente na timeline, se existir, senão gera um genérico const patternNode = allPatternsArray[index];
const bbTrackName = const bbTrackName = bbTrack.getAttribute("name") || `Pattern ${index + 1}`;
sortedBBTrackNameNodes[index] &&
sortedBBTrackNameNodes[index].getAttribute("name")
? sortedBBTrackNameNodes[index].getAttribute("name")
: `Pattern ${index + 1}`;
if (!patternNode) { if (!patternNode) {
return { return {
@ -139,7 +135,10 @@ function parseInstrumentNode(
const steps = new Array(patternSteps).fill(false); const steps = new Array(patternSteps).fill(false);
const notes = []; const notes = [];
const ticksPerStep = 48; // 192 / 4 // === CORREÇÃO MATEMÁTICA ===
// No LMMS, 1 semínima (beat) = 192 ticks.
// 1 semicolcheia (1/16 step) = 192 / 4 = 48 ticks.
const ticksPerStep = 48;
patternNode.querySelectorAll("note").forEach((noteNode) => { patternNode.querySelectorAll("note").forEach((noteNode) => {
const pos = parseInt(noteNode.getAttribute("pos"), 10); const pos = parseInt(noteNode.getAttribute("pos"), 10);
@ -151,12 +150,8 @@ function parseInstrumentNode(
pan: parseInt(noteNode.getAttribute("pan"), 10), pan: parseInt(noteNode.getAttribute("pan"), 10),
}); });
// Calcula o step visual (para o beat editor) // Calcula qual quadradinho acender
// Se o pos for > patternSteps * 48 (ex: compasso 2), precisamos normalizar se quisermos mostrar tudo junto const stepIndex = Math.round(pos / ticksPerStep);
// Mas para manter simples, pegamos o relativo:
const relativePos = pos % (patternSteps * ticksPerStep);
const stepIndex = Math.round(relativePos / ticksPerStep);
if (stepIndex < patternSteps) steps[stepIndex] = true; if (stepIndex < patternSteps) steps[stepIndex] = true;
}); });
@ -168,7 +163,7 @@ function parseInstrumentNode(
}; };
}); });
// Lógica de Sample vs Plugin (mantida igual) // Lógica de Sample vs Plugin
let finalSamplePath = null; let finalSamplePath = null;
let trackType = "plugin"; let trackType = "plugin";
@ -197,13 +192,13 @@ function parseInstrumentNode(
name: trackName, name: trackName,
type: trackType, type: trackType,
samplePath: finalSamplePath, samplePath: finalSamplePath,
patterns: patterns, // Agora contém TODAS as patterns (pos 0, 192, etc) patterns: patterns,
activePatternIndex: 0, activePatternIndex: 0,
volume: !isNaN(volFromFile) ? volFromFile / 100 : DEFAULT_VOLUME, volume: !isNaN(volFromFile) ? volFromFile / 100 : DEFAULT_VOLUME,
pan: !isNaN(panFromFile) ? panFromFile / 100 : DEFAULT_PAN, pan: !isNaN(panFromFile) ? panFromFile / 100 : DEFAULT_PAN,
instrumentName: instrumentName, instrumentName: instrumentName,
instrumentXml: instrumentNode.innerHTML, instrumentXml: instrumentNode.innerHTML,
parentBasslineId: parentBasslineId, parentBasslineId: parentBasslineId, // Guarda o ID do pai para filtragem na UI
}; };
} }

View File

@ -657,21 +657,19 @@
// --- B. Steps (Correção Aqui) --- // --- B. Steps (Correção Aqui) ---
let stepData = []; let stepData = [];
// LÓGICA ATUALIZADA DE VISUALIZAÇÃO
// Se houver múltiplos patterns (loop longo), combinamos os steps ativos
// ou pegamos o pattern que realmente tem notas.
if (inst.patterns && inst.patterns.length > 0) { if (inst.patterns && inst.patterns.length > 0) {
// Cria um array base de 16 steps (ou maior se quiser suportar 32/64) // Tenta encontrar um pattern que tenha pelo menos uma nota 'true'
stepData = new Array(16).fill(false); const activePattern = inst.patterns.find((p) =>
p.steps.some((s) => s === true)
);
inst.patterns.forEach((p) => { if (activePattern) {
// Mescla os steps desse pattern no array principal visual // Se achou um com notas, usa ele
if (p.steps) { stepData = activePattern.steps;
p.steps.forEach((isActive, idx) => { } else {
if (isActive && idx < 16) stepData[idx] = true; // Se todos estão vazios, usa o primeiro mesmo
}); stepData = inst.patterns[0].steps;
} }
});
} else { } else {
stepData = Array(16).fill(false); stepData = Array(16).fill(false);
} }