criação de novas patterns de composição nos projetos
This commit is contained in:
1 parent
f80d6511a4
commit
2d40bf747f
3 files changed
+118
-23
No files matched your search
@@ -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;
|
||||
|
||||
|
||||
Reference in new issue
Block a user