melhorando a leitura de projetos no mmpCreator
Deploy / Deploy (push) Successful in 2m7s
Details
Deploy / Deploy (push) Successful in 2m7s
Details
This commit is contained in:
parent
51b408909e
commit
9c7f62ada4
|
|
@ -323,6 +323,16 @@ body.sidebar-hidden .sample-browser { width: 0; min-width: 0; border-right: none
|
|||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
overflow-x: auto; /* barra horizontal */
|
||||
overflow-y: auto; /* se quiser rolar vertical com várias tracks */
|
||||
}
|
||||
|
||||
/* Importantíssimo: esses caras precisam poder ficar mais largos que a tela */
|
||||
#audio-timeline-ruler,
|
||||
#audio-track-container{
|
||||
position: relative;
|
||||
min-width: 100%; /* no mínimo ocupa a viewport */
|
||||
}
|
||||
|
||||
#audio-track-container { flex-grow: 1; overflow: auto; }
|
||||
|
|
|
|||
|
|
@ -57,19 +57,47 @@ export function renderAudioEditor() {
|
|||
|
||||
const pixelsPerSecond = getPixelsPerSecond();
|
||||
|
||||
let maxTime = appState.global.loopEndTime;
|
||||
appState.audio.clips.forEach((clip) => {
|
||||
let maxTime = appState.global.loopEndTime || 0;
|
||||
|
||||
// áudio (segundos)
|
||||
(appState.audio.clips || []).forEach((clip) => {
|
||||
const endTime =
|
||||
(clip.startTimeInSeconds || 0) + (clip.durationInSeconds || 0);
|
||||
if (endTime > maxTime) maxTime = endTime;
|
||||
});
|
||||
|
||||
const containerWidth = existingTrackContainer.offsetWidth;
|
||||
// basslines (ticks -> steps -> segundos)
|
||||
const TICKS_PER_STEP = 12; // você já usa 12 na renderização do bassline
|
||||
const secondsPerStep = getSecondsPerStep();
|
||||
|
||||
if (appState.pattern?.tracks) {
|
||||
appState.pattern.tracks.forEach((t) => {
|
||||
if (t.type !== "bassline" || !Array.isArray(t.playlist_clips)) return;
|
||||
|
||||
t.playlist_clips.forEach((c) => {
|
||||
const endTicks = (c.pos || 0) + (c.len || 0);
|
||||
const endSteps = endTicks / TICKS_PER_STEP;
|
||||
const endTimeSec = endSteps * secondsPerStep;
|
||||
if (endTimeSec > maxTime) maxTime = endTimeSec;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const containerWidth =
|
||||
tracksParent.clientWidth || existingTrackContainer.offsetWidth;
|
||||
|
||||
const contentWidth = maxTime * pixelsPerSecond;
|
||||
const totalWidth = Math.max(contentWidth, containerWidth, 2000);
|
||||
|
||||
// não encolhe se já tiver sido expandido antes
|
||||
const previousWidth = appState.audio.timelineWidthPx || 0;
|
||||
|
||||
const totalWidth = Math.max(contentWidth, containerWidth, previousWidth, 2000);
|
||||
|
||||
appState.audio.timelineWidthPx = totalWidth;
|
||||
|
||||
ruler.style.width = `${totalWidth}px`;
|
||||
|
||||
|
||||
const zoomFactor = ZOOM_LEVELS[appState.global.zoomLevelIndex];
|
||||
const beatsPerBar = getBeatsPerBar();
|
||||
const stepWidthPx = PIXELS_PER_STEP * zoomFactor;
|
||||
|
|
@ -461,14 +489,61 @@ export function renderAudioEditor() {
|
|||
});
|
||||
|
||||
// Sync Scroll
|
||||
function appendRulerMarkers(rulerEl, oldWidth, newWidth, barWidthPx) {
|
||||
if (!rulerEl || barWidthPx <= 0) return;
|
||||
|
||||
const loopEl = rulerEl.querySelector("#loop-region");
|
||||
const startBar = Math.floor(oldWidth / barWidthPx) + 1;
|
||||
const endBar = Math.ceil(newWidth / barWidthPx);
|
||||
|
||||
for (let i = startBar; i <= endBar; i++) {
|
||||
const marker = document.createElement("div");
|
||||
marker.className = "ruler-marker";
|
||||
marker.textContent = i;
|
||||
marker.style.left = `${(i - 1) * barWidthPx}px`;
|
||||
// mantém loop por cima/ordem estável
|
||||
rulerEl.insertBefore(marker, loopEl || null);
|
||||
}
|
||||
}
|
||||
|
||||
function applyTimelineWidth(widthPx) {
|
||||
appState.audio.timelineWidthPx = widthPx;
|
||||
|
||||
const r = tracksParent.querySelector(".timeline-ruler");
|
||||
if (r) r.style.width = `${widthPx}px`;
|
||||
|
||||
tracksParent
|
||||
.querySelectorAll(".spectrogram-view-grid")
|
||||
.forEach((g) => (g.style.width = `${widthPx}px`));
|
||||
}
|
||||
|
||||
newTrackContainer.addEventListener("scroll", () => {
|
||||
const scrollPos = newTrackContainer.scrollLeft;
|
||||
const mainRuler = document.querySelector(".timeline-ruler");
|
||||
|
||||
// sync ruler
|
||||
const mainRuler = tracksParent.querySelector(".timeline-ruler");
|
||||
if (mainRuler && mainRuler.scrollLeft !== scrollPos) {
|
||||
mainRuler.scrollLeft = scrollPos;
|
||||
}
|
||||
|
||||
// expansão "infinita"
|
||||
const threshold = 300;
|
||||
const rightEdge = scrollPos + newTrackContainer.clientWidth;
|
||||
const currentWidth = appState.audio.timelineWidthPx || totalWidth;
|
||||
|
||||
if (rightEdge > currentWidth - threshold) {
|
||||
const newWidth = Math.ceil(currentWidth * 1.5);
|
||||
|
||||
// aplica widths
|
||||
applyTimelineWidth(newWidth);
|
||||
|
||||
// adiciona mais marcadores na régua (sem re-render geral)
|
||||
const rulerEl = tracksParent.querySelector(".timeline-ruler");
|
||||
appendRulerMarkers(rulerEl, currentWidth, newWidth, barWidthPx);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Event Listener Principal (mousedown)
|
||||
newTrackContainer.addEventListener("mousedown", (e) => {
|
||||
document.getElementById("timeline-context-menu").style.display = "none";
|
||||
|
|
|
|||
Loading…
Reference in New Issue