criação de novas patterns de composição nos projetos

This commit is contained in:
JotaChina committed 2025-12-27 18:50:36 -03:00
1 parent f80d6511a4
commit 2d40bf747f
3 files changed
+118 -23

No files matched your search

+76
View File
@@ -499,11 +499,15 @@ function _ensureBasslineForPatternIndex(patternIndex) {
instrumentSourceId: null,
volume: 1,
pan: 0,
instrumentSourceId: _getDefaultRackId(),
};
appState.pattern.tracks.push(b);
}
if (!Array.isArray(b.playlist_clips)) b.playlist_clips = [];
// Isso deixa o modo focado funcionando em patterns recém-criados.
if (!b.instrumentSourceId) b.instrumentSourceId = _getDefaultRackId();
// garante ids nos clips antigos
b.playlist_clips.forEach((c) => {
@@ -513,6 +517,13 @@ function _ensureBasslineForPatternIndex(patternIndex) {
return b;
}
function _getDefaultRackId() {
const inst = (appState.pattern.tracks || []).find(
(t) => t.type !== "bassline" && t.parentBasslineId
);
return inst?.parentBasslineId ?? null;
}
// -----------------------------------------------------------------------------
// BROADCAST
// -----------------------------------------------------------------------------
@@ -708,6 +719,71 @@ async function handleActionBroadcast(action) {
break;
}
case "ADD_PATTERN": {
const who = actorOf(action);
const desiredIndex = Number.isFinite(Number(action.patternIndex))
? Number(action.patternIndex)
: null;
const nonBass = (appState.pattern.tracks || []).filter(t => t.type !== "bassline");
const currentCount = nonBass.reduce((m, t) => Math.max(m, t.patterns?.length ?? 0), 0);
const idx = desiredIndex != null ? desiredIndex : currentCount;
const finalName = String(action.name || `Pattern ${idx + 1}`).trim();
// 1) cria patterns vazios em TODAS as tracks (respeita bars-input)
_ensurePatternsUpTo(idx);
// 2) garante nome/pos estáveis no índice criado
for (const t of nonBass) {
t.patterns[idx] = t.patterns[idx] || _makeEmptyPattern(idx);
t.patterns[idx].name = finalName;
if (t.patterns[idx].pos == null) t.patterns[idx].pos = idx * LMMS_BAR_TICKS;
}
// 3) cria a lane "bassline" (a coluna do pattern)
const b = _ensureBasslineForPatternIndex(idx);
b.patternIndex = idx;
b.name = finalName;
if (!b.instrumentSourceId) b.instrumentSourceId = _getDefaultRackId();
// 4) opcional: já selecionar
if (action.select) {
appState.pattern.activePatternIndex = idx;
appState.pattern.tracks.forEach((track) => (track.activePatternIndex = idx));
}
renderAll();
showToast(`➕ ${who} criou: ${finalName}`, "success");
saveStateToSession();
break;
}
case "REMOVE_LAST_PATTERN": {
const nonBass = (appState.pattern.tracks || []).filter(t => t.type !== "bassline");
const count = nonBass.reduce((m, t) => Math.max(m, t.patterns?.length ?? 0), 0);
const last = count - 1;
if (last <= 0) break;
// remove patterns nas tracks
for (const t of nonBass) t.patterns.pop();
// remove a lane bassline correspondente
appState.pattern.tracks = appState.pattern.tracks.filter(
t => !(t.type === "bassline" && Number(t.patternIndex) === last)
);
// ajusta seleção
const newIdx = Math.min(appState.pattern.activePatternIndex, last - 1);
appState.pattern.activePatternIndex = newIdx;
appState.pattern.tracks.forEach((t) => (t.activePatternIndex = newIdx));
renderAll();
saveStateToSession();
break;
}
case "ADD_PLAYLIST_PATTERN_CLIP": {
const { patternIndex, pos, len, clipId, name } = action;