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(
|
function parseInstrumentNode(
|
||||||
trackNode,
|
trackNode,
|
||||||
sortedBBTrackNameNodes,
|
sortedBBTrackNameNodes, // Esse argumento agora será ignorado para evitar o bug
|
||||||
pathMap,
|
pathMap,
|
||||||
parentBasslineId = null
|
parentBasslineId = null
|
||||||
) {
|
) {
|
||||||
|
|
@ -237,8 +237,14 @@ function parseInstrumentNode(
|
||||||
const trackName = trackNode.getAttribute("name");
|
const trackName = trackNode.getAttribute("name");
|
||||||
const instrumentName = instrumentNode.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");
|
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) => {
|
const allPatternsArray = Array.from(allPatternsNodeList).sort((a, b) => {
|
||||||
return (
|
return (
|
||||||
(parseInt(a.getAttribute("pos"), 10) || 0) -
|
(parseInt(a.getAttribute("pos"), 10) || 0) -
|
||||||
|
|
@ -246,55 +252,56 @@ function parseInstrumentNode(
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const patternsToCreate =
|
// Se não houver patterns no XML, criamos um vazio para não quebrar a UI
|
||||||
sortedBBTrackNameNodes.length > 0
|
let patterns = [];
|
||||||
? sortedBBTrackNameNodes
|
|
||||||
: [{ getAttribute: () => "Pattern 1" }];
|
|
||||||
|
|
||||||
const patterns = patternsToCreate.map((bbTrack, index) => {
|
if (allPatternsArray.length > 0) {
|
||||||
const patternNode = allPatternsArray[index];
|
patterns = allPatternsArray.map((patternNode, index) => {
|
||||||
const bbTrackName = bbTrack.getAttribute("name") || `Pattern ${index + 1}`;
|
// Tenta pegar o nome do atributo, ou gera um genérico
|
||||||
|
const patternName = patternNode.getAttribute("name") || `Pattern ${index}`;
|
||||||
|
|
||||||
if (!patternNode) {
|
const patternSteps = parseInt(patternNode.getAttribute("steps"), 10) || 16;
|
||||||
return {
|
const steps = new Array(patternSteps).fill(false);
|
||||||
name: bbTrackName,
|
const notes = [];
|
||||||
steps: new Array(16).fill(false),
|
|
||||||
notes: [],
|
|
||||||
pos: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const patternSteps = parseInt(patternNode.getAttribute("steps"), 10) || 16;
|
// Constante de conversão LMMS (192 ticks = 1 beat, 48 ticks = 1 step)
|
||||||
const steps = new Array(patternSteps).fill(false);
|
const ticksPerStep = 48;
|
||||||
const notes = [];
|
|
||||||
|
|
||||||
// === CORREÇÃO MATEMÁTICA ===
|
patternNode.querySelectorAll("note").forEach((noteNode) => {
|
||||||
// No LMMS, 1 semínima (beat) = 192 ticks.
|
const pos = parseInt(noteNode.getAttribute("pos"), 10);
|
||||||
// 1 semicolcheia (1/16 step) = 192 / 4 = 48 ticks.
|
const len = parseInt(noteNode.getAttribute("len"), 10);
|
||||||
const ticksPerStep = 48;
|
const vol = parseInt(noteNode.getAttribute("vol"), 10);
|
||||||
|
const pan = parseInt(noteNode.getAttribute("pan"), 10);
|
||||||
|
const key = parseInt(noteNode.getAttribute("key"), 10);
|
||||||
|
|
||||||
patternNode.querySelectorAll("note").forEach((noteNode) => {
|
notes.push({ pos, len, key, vol, pan });
|
||||||
const pos = parseInt(noteNode.getAttribute("pos"), 10);
|
|
||||||
notes.push({
|
// Calcula qual step acender
|
||||||
pos: pos,
|
// Nota: B/B Editor no LMMS geralmente usa notas de len=48.
|
||||||
len: parseInt(noteNode.getAttribute("len"), 10),
|
// Se a nota for longa, isso marca apenas o step de início.
|
||||||
key: parseInt(noteNode.getAttribute("key"), 10),
|
const stepIndex = Math.round(pos / ticksPerStep);
|
||||||
vol: parseInt(noteNode.getAttribute("vol"), 10),
|
|
||||||
pan: parseInt(noteNode.getAttribute("pan"), 10),
|
if (stepIndex >= 0 && stepIndex < patternSteps) {
|
||||||
|
steps[stepIndex] = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Calcula qual quadradinho acender
|
return {
|
||||||
const stepIndex = Math.round(pos / ticksPerStep);
|
name: patternName,
|
||||||
if (stepIndex < patternSteps) steps[stepIndex] = true;
|
steps: steps,
|
||||||
|
notes: notes,
|
||||||
|
pos: parseInt(patternNode.getAttribute("pos"), 10) || 0,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
return {
|
// Fallback: Nenhum pattern encontrado no XML, cria um padrão vazio
|
||||||
name: bbTrackName,
|
patterns.push({
|
||||||
steps: steps,
|
name: "Pattern 0",
|
||||||
notes: notes,
|
steps: new Array(16).fill(false),
|
||||||
pos: parseInt(patternNode.getAttribute("pos"), 10) || 0,
|
notes: [],
|
||||||
};
|
pos: 0
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Lógica de Sample vs Plugin
|
// Lógica de Sample vs Plugin
|
||||||
let finalSamplePath = null;
|
let finalSamplePath = null;
|
||||||
|
|
@ -326,12 +333,12 @@ function parseInstrumentNode(
|
||||||
type: trackType,
|
type: trackType,
|
||||||
samplePath: finalSamplePath,
|
samplePath: finalSamplePath,
|
||||||
patterns: patterns,
|
patterns: patterns,
|
||||||
activePatternIndex: 0,
|
activePatternIndex: 0, // Sempre começa mostrando o primeiro pattern disponível
|
||||||
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, // Guarda o ID do pai para filtragem na UI
|
parentBasslineId: parentBasslineId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue