atualizando em tempo real as patterns no editor de patterns e playlist
This commit is contained in:
1 parent
7eeed3ee92
commit
443685ac72
3 files changed
+153
-98
No files matched your search
@@ -507,6 +507,34 @@ socket.on("action_broadcast", (payload) => {
|
||||
// -----------------------------------------------------------------------------
|
||||
// PROCESSAR AÇÕES
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const LMMS_BAR_TICKS = 192;
|
||||
const STEPS_PER_BAR = 16;
|
||||
|
||||
function _makeEmptyPattern(idx) {
|
||||
// tenta respeitar bars-input atual, mas nunca menos que 1 bar
|
||||
const bars = parseInt(document.getElementById("bars-input")?.value, 10) || 1;
|
||||
const stepsLen = Math.max(STEPS_PER_BAR, bars * STEPS_PER_BAR);
|
||||
|
||||
return {
|
||||
name: `Pattern ${idx + 1}`,
|
||||
steps: new Array(stepsLen).fill(false),
|
||||
notes: [],
|
||||
pos: idx * LMMS_BAR_TICKS,
|
||||
};
|
||||
}
|
||||
|
||||
function _ensurePatternsUpTo(patternIndex) {
|
||||
appState.pattern.tracks.forEach((t) => {
|
||||
if (t.type === "bassline") return;
|
||||
|
||||
if (!Array.isArray(t.patterns)) t.patterns = [];
|
||||
while (t.patterns.length <= patternIndex) {
|
||||
t.patterns.push(_makeEmptyPattern(t.patterns.length));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let isLoadingProject = false;
|
||||
async function handleActionBroadcast(action) {
|
||||
if (!action || !action.type) return;
|
||||
@@ -995,29 +1023,34 @@ async function handleActionBroadcast(action) {
|
||||
|
||||
// Notes
|
||||
case "TOGGLE_NOTE": {
|
||||
const { trackIndex: ti, patternIndex: pi, stepIndex: si, isActive } = action;
|
||||
const { trackIndex: ti, patternIndex: pi, stepIndex: si, isActive } = action;
|
||||
|
||||
// ✅ garante que o índice exista em todas as tracks (evita “silêncio” na playlist)
|
||||
_ensurePatternsUpTo(pi);
|
||||
|
||||
const t = appState.pattern.tracks[ti];
|
||||
if (t) {
|
||||
t.patterns[pi] = t.patterns[pi] || _makeEmptyPattern(pi);
|
||||
|
||||
// mantém metadados estáveis p/ export/sync
|
||||
if (t.patterns[pi].pos == null) t.patterns[pi].pos = pi * LMMS_BAR_TICKS;
|
||||
if (!t.patterns[pi].name) t.patterns[pi].name = `Pattern ${pi + 1}`;
|
||||
if (!Array.isArray(t.patterns[pi].notes)) t.patterns[pi].notes = [];
|
||||
|
||||
const t = appState.pattern.tracks[ti];
|
||||
if (t) {
|
||||
t.patterns[pi] = t.patterns[pi] || { steps: [] };
|
||||
t.patterns[pi].steps[si] = isActive;
|
||||
|
||||
try { updateStepUI(ti, pi, si, isActive); } catch {}
|
||||
if (!isFromSelf) schedulePatternRerender();
|
||||
}
|
||||
}
|
||||
|
||||
// ✔ ADICIONE ISTO
|
||||
if (window.ROOM_NAME && isFromSelf) {
|
||||
const xml = generateXmlFromStateExported();
|
||||
sendAction({
|
||||
type: "SYNC_PATTERN_STATE",
|
||||
xml
|
||||
});
|
||||
}
|
||||
if (window.ROOM_NAME && isFromSelf) {
|
||||
const xml = generateXmlFromStateExported();
|
||||
sendAction({ type: "SYNC_PATTERN_STATE", xml });
|
||||
}
|
||||
|
||||
saveStateToSession();
|
||||
break;
|
||||
}
|
||||
saveStateToSession();
|
||||
break;
|
||||
}
|
||||
|
||||
case "UPDATE_PATTERN_NOTES": {
|
||||
const {
|
||||
@@ -1102,6 +1135,9 @@ async function handleActionBroadcast(action) {
|
||||
track.activePatternIndex = patternIndex;
|
||||
});
|
||||
|
||||
// ✅ garante que TODAS as tracks tenham esse índice disponível
|
||||
_ensurePatternsUpTo(patternIndex);
|
||||
|
||||
try {
|
||||
const stepsPerBar = 16; // 4/4 em 1/16
|
||||
|
||||
|
||||
Reference in new issue
Block a user