melhorando a leitura de projetos no mmpCreator
Deploy / Deploy (push) Successful in 2m41s
Details
Deploy / Deploy (push) Successful in 2m41s
Details
This commit is contained in:
parent
d86348cfac
commit
08302947ad
|
|
@ -225,7 +225,7 @@ export async function loadProjectFromServer(fileName) {
|
|||
// =================================================================
|
||||
function parseInstrumentNode(
|
||||
trackNode,
|
||||
sortedBBTrackNameNodes,
|
||||
sortedBBTrackNameNodes, // Esse argumento agora será ignorado para evitar o bug
|
||||
pathMap,
|
||||
parentBasslineId = null
|
||||
) {
|
||||
|
|
@ -237,8 +237,14 @@ function parseInstrumentNode(
|
|||
const trackName = trackNode.getAttribute("name");
|
||||
const instrumentName = instrumentNode.getAttribute("name");
|
||||
|
||||
// Lógica de Patterns
|
||||
// Lógica de Patterns:
|
||||
// CORREÇÃO: Iteramos diretamente sobre os patterns encontrados no XML do instrumento.
|
||||
// Não tentamos mais mapear 1-para-1 com os clipes da timeline, pois instrumentos de
|
||||
// Beat/Bassline reutilizam o mesmo pattern várias vezes.
|
||||
|
||||
const allPatternsNodeList = trackNode.querySelectorAll("pattern");
|
||||
|
||||
// Ordena os patterns pela posição (importante para Song Editor, neutro para BB Editor)
|
||||
const allPatternsArray = Array.from(allPatternsNodeList).sort((a, b) => {
|
||||
return (
|
||||
(parseInt(a.getAttribute("pos"), 10) || 0) -
|
||||
|
|
@ -246,55 +252,56 @@ function parseInstrumentNode(
|
|||
);
|
||||
});
|
||||
|
||||
const patternsToCreate =
|
||||
sortedBBTrackNameNodes.length > 0
|
||||
? sortedBBTrackNameNodes
|
||||
: [{ getAttribute: () => "Pattern 1" }];
|
||||
// Se não houver patterns no XML, criamos um vazio para não quebrar a UI
|
||||
let patterns = [];
|
||||
|
||||
const patterns = patternsToCreate.map((bbTrack, index) => {
|
||||
const patternNode = allPatternsArray[index];
|
||||
const bbTrackName = bbTrack.getAttribute("name") || `Pattern ${index + 1}`;
|
||||
|
||||
if (!patternNode) {
|
||||
return {
|
||||
name: bbTrackName,
|
||||
steps: new Array(16).fill(false),
|
||||
notes: [],
|
||||
pos: 0,
|
||||
};
|
||||
}
|
||||
if (allPatternsArray.length > 0) {
|
||||
patterns = allPatternsArray.map((patternNode, index) => {
|
||||
// Tenta pegar o nome do atributo, ou gera um genérico
|
||||
const patternName = patternNode.getAttribute("name") || `Pattern ${index}`;
|
||||
|
||||
const patternSteps = parseInt(patternNode.getAttribute("steps"), 10) || 16;
|
||||
const steps = new Array(patternSteps).fill(false);
|
||||
const notes = [];
|
||||
|
||||
// === CORREÇÃO MATEMÁTICA ===
|
||||
// No LMMS, 1 semínima (beat) = 192 ticks.
|
||||
// 1 semicolcheia (1/16 step) = 192 / 4 = 48 ticks.
|
||||
// Constante de conversão LMMS (192 ticks = 1 beat, 48 ticks = 1 step)
|
||||
const ticksPerStep = 48;
|
||||
|
||||
patternNode.querySelectorAll("note").forEach((noteNode) => {
|
||||
const pos = parseInt(noteNode.getAttribute("pos"), 10);
|
||||
notes.push({
|
||||
pos: pos,
|
||||
len: parseInt(noteNode.getAttribute("len"), 10),
|
||||
key: parseInt(noteNode.getAttribute("key"), 10),
|
||||
vol: parseInt(noteNode.getAttribute("vol"), 10),
|
||||
pan: parseInt(noteNode.getAttribute("pan"), 10),
|
||||
});
|
||||
const len = parseInt(noteNode.getAttribute("len"), 10);
|
||||
const vol = parseInt(noteNode.getAttribute("vol"), 10);
|
||||
const pan = parseInt(noteNode.getAttribute("pan"), 10);
|
||||
const key = parseInt(noteNode.getAttribute("key"), 10);
|
||||
|
||||
// Calcula qual quadradinho acender
|
||||
notes.push({ pos, len, key, vol, pan });
|
||||
|
||||
// Calcula qual step acender
|
||||
// Nota: B/B Editor no LMMS geralmente usa notas de len=48.
|
||||
// Se a nota for longa, isso marca apenas o step de início.
|
||||
const stepIndex = Math.round(pos / ticksPerStep);
|
||||
if (stepIndex < patternSteps) steps[stepIndex] = true;
|
||||
|
||||
if (stepIndex >= 0 && stepIndex < patternSteps) {
|
||||
steps[stepIndex] = true;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
name: bbTrackName,
|
||||
name: patternName,
|
||||
steps: steps,
|
||||
notes: notes,
|
||||
pos: parseInt(patternNode.getAttribute("pos"), 10) || 0,
|
||||
};
|
||||
});
|
||||
} else {
|
||||
// Fallback: Nenhum pattern encontrado no XML, cria um padrão vazio
|
||||
patterns.push({
|
||||
name: "Pattern 0",
|
||||
steps: new Array(16).fill(false),
|
||||
notes: [],
|
||||
pos: 0
|
||||
});
|
||||
}
|
||||
|
||||
// Lógica de Sample vs Plugin
|
||||
let finalSamplePath = null;
|
||||
|
|
@ -326,12 +333,12 @@ function parseInstrumentNode(
|
|||
type: trackType,
|
||||
samplePath: finalSamplePath,
|
||||
patterns: patterns,
|
||||
activePatternIndex: 0,
|
||||
activePatternIndex: 0, // Sempre começa mostrando o primeiro pattern disponível
|
||||
volume: !isNaN(volFromFile) ? volFromFile / 100 : DEFAULT_VOLUME,
|
||||
pan: !isNaN(panFromFile) ? panFromFile / 100 : DEFAULT_PAN,
|
||||
instrumentName: instrumentName,
|
||||
instrumentXml: instrumentNode.innerHTML,
|
||||
parentBasslineId: parentBasslineId, // Guarda o ID do pai para filtragem na UI
|
||||
parentBasslineId: parentBasslineId,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue