diff --git a/assets/js/creations/file.js b/assets/js/creations/file.js index 38285340..69acace9 100755 --- a/assets/js/creations/file.js +++ b/assets/js/creations/file.js @@ -104,7 +104,7 @@ function parseInstrumentNode( const trackName = trackNode.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 allPatternsArray = Array.from(allPatternsNodeList).sort((a, b) => { return ( @@ -113,18 +113,14 @@ function parseInstrumentNode( ); }); - // 2. CORREÇÃO PRINCIPAL: - // O loop deve ser baseado nos patterns existentes no XML, não nos blocos da timeline (bbtco). - // Se não houver patterns no XML (instrumento vazio), criamos um array com 1 item para gerar o pattern default. - const loopSource = allPatternsArray.length > 0 ? allPatternsArray : [null]; + const patternsToCreate = + sortedBBTrackNameNodes.length > 0 + ? sortedBBTrackNameNodes + : [{ getAttribute: () => "Pattern 1" }]; - const patterns = loopSource.map((patternNode, index) => { - // Tenta pegar o nome do bloco correspondente na timeline, se existir, senão gera um genérico - const bbTrackName = - sortedBBTrackNameNodes[index] && - sortedBBTrackNameNodes[index].getAttribute("name") - ? sortedBBTrackNameNodes[index].getAttribute("name") - : `Pattern ${index + 1}`; + const patterns = patternsToCreate.map((bbTrack, index) => { + const patternNode = allPatternsArray[index]; + const bbTrackName = bbTrack.getAttribute("name") || `Pattern ${index + 1}`; if (!patternNode) { return { @@ -139,7 +135,10 @@ function parseInstrumentNode( const steps = new Array(patternSteps).fill(false); 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) => { const pos = parseInt(noteNode.getAttribute("pos"), 10); @@ -151,12 +150,8 @@ function parseInstrumentNode( pan: parseInt(noteNode.getAttribute("pan"), 10), }); - // Calcula o step visual (para o beat editor) - // Se o pos for > patternSteps * 48 (ex: compasso 2), precisamos normalizar se quisermos mostrar tudo junto - // Mas para manter simples, pegamos o relativo: - const relativePos = pos % (patternSteps * ticksPerStep); - const stepIndex = Math.round(relativePos / ticksPerStep); - + // Calcula qual quadradinho acender + const stepIndex = Math.round(pos / ticksPerStep); 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 trackType = "plugin"; @@ -197,13 +192,13 @@ function parseInstrumentNode( name: trackName, type: trackType, samplePath: finalSamplePath, - patterns: patterns, // Agora contém TODAS as patterns (pos 0, 192, etc) + patterns: patterns, activePatternIndex: 0, volume: !isNaN(volFromFile) ? volFromFile / 100 : DEFAULT_VOLUME, pan: !isNaN(panFromFile) ? panFromFile / 100 : DEFAULT_PAN, instrumentName: instrumentName, instrumentXml: instrumentNode.innerHTML, - parentBasslineId: parentBasslineId, + parentBasslineId: parentBasslineId, // Guarda o ID do pai para filtragem na UI }; } diff --git a/creation.html b/creation.html index f17201d9..e0fb209b 100755 --- a/creation.html +++ b/creation.html @@ -657,21 +657,19 @@ // --- B. Steps (Correção Aqui) --- 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) { - // Cria um array base de 16 steps (ou maior se quiser suportar 32/64) - stepData = new Array(16).fill(false); + // Tenta encontrar um pattern que tenha pelo menos uma nota 'true' + const activePattern = inst.patterns.find((p) => + p.steps.some((s) => s === true) + ); - inst.patterns.forEach((p) => { - // Mescla os steps desse pattern no array principal visual - if (p.steps) { - p.steps.forEach((isActive, idx) => { - if (isActive && idx < 16) stepData[idx] = true; - }); - } - }); + if (activePattern) { + // Se achou um com notas, usa ele + stepData = activePattern.steps; + } else { + // Se todos estão vazios, usa o primeiro mesmo + stepData = inst.patterns[0].steps; + } } else { stepData = Array(16).fill(false); }