diff options
Diffstat (limited to 'tools/timeline_editor/index.html')
| -rw-r--r-- | tools/timeline_editor/index.html | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/tools/timeline_editor/index.html b/tools/timeline_editor/index.html index 94e88f6..d450522 100644 --- a/tools/timeline_editor/index.html +++ b/tools/timeline_editor/index.html @@ -372,6 +372,7 @@ <button id="saveBtn" disabled>💾 Save demo.seq</button> <button id="addSequenceBtn" disabled>➕ Add Sequence</button> <button id="deleteBtn" disabled>🗑️ Delete Selected</button> + <button id="reorderBtn" disabled>🔄 Re-order by Time</button> </div> <div class="zoom-controls"> @@ -423,6 +424,7 @@ const saveBtn = document.getElementById('saveBtn'); const addSequenceBtn = document.getElementById('addSequenceBtn'); const deleteBtn = document.getElementById('deleteBtn'); + const reorderBtn = document.getElementById('reorderBtn'); const propertiesPanel = document.getElementById('propertiesPanel'); const propertiesContent = document.getElementById('propertiesContent'); const messageArea = document.getElementById('messageArea'); @@ -868,6 +870,7 @@ renderTimeline(); saveBtn.disabled = false; addSequenceBtn.disabled = false; + reorderBtn.disabled = false; showMessage(`Loaded ${currentFile} - ${sequences.length} sequences`, 'success'); } catch (err) { showMessage(`Error parsing file: ${err.message}`, 'error'); @@ -916,6 +919,30 @@ showMessage('Item deleted', 'success'); }); + // Re-order sequences by time + reorderBtn.addEventListener('click', () => { + // Store current active sequence (if any) + const currentActiveSeq = lastActiveSeqIndex >= 0 ? sequences[lastActiveSeqIndex] : null; + + // Sort sequences by start time (ascending) + sequences.sort((a, b) => a.startTime - b.startTime); + + // Re-render timeline + renderTimeline(); + + // Restore focus on previously active sequence + if (currentActiveSeq) { + const newIndex = sequences.indexOf(currentActiveSeq); + if (newIndex >= 0 && sequences[newIndex]._yPosition !== undefined) { + // Scroll to keep it in view + timelineContainer.scrollTop = sequences[newIndex]._yPosition; + lastActiveSeqIndex = newIndex; + } + } + + showMessage('Sequences re-ordered by start time', 'success'); + }); + // Zoom zoomSlider.addEventListener('input', (e) => { const zoom = parseInt(e.target.value); @@ -963,12 +990,14 @@ // Horizontal scroll timelineContainer.scrollLeft += e.deltaY; - // Calculate current time position (left edge of viewport) + // Calculate current time position with 10% headroom for visual comfort const currentScrollLeft = timelineContainer.scrollLeft; - const currentTime = currentScrollLeft / pixelsPerSecond; + const viewportWidth = timelineContainer.clientWidth; + const slack = (viewportWidth / pixelsPerSecond) * 0.1; // 10% of viewport width in seconds + const currentTime = (currentScrollLeft / pixelsPerSecond) + slack; // Find the closest sequence that should be visible at current time - // (the last sequence that starts before or at current time) + // (the last sequence that starts before or at current time + slack) let targetSeqIndex = 0; for (let i = 0; i < sequences.length; i++) { if (sequences[i].startTime <= currentTime) { |
