1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
|
# Timeline Editor - Feature Roadmap
This document outlines planned enhancements for the interactive timeline editor.
---
## Phase 1: Core Editing Features (High Priority)
### 1.1 Snap-to-Beat ⭐ Priority: HIGH
**Goal:** Enable precise musical timing by snapping items to beat boundaries.
**Features:**
- Parse BPM from demo.seq file (`# BPM 120`)
- Calculate beat grid based on BPM (e.g., 120 BPM = 0.5s per beat)
- Visual beat markers on timeline (lighter gray lines between second markers)
- Toggle snap mode (keyboard shortcut: `S` key)
- When dragging, snap position to nearest beat
- Status indicator showing current snap mode and BPM
**Implementation Details:**
```javascript
// Calculate beat positions
const beatsPerSecond = bpm / 60.0;
const secondsPerBeat = 60.0 / bpm;
// Snap function
function snapToBeat(timeInSeconds) {
if (!snapEnabled) return timeInSeconds;
const beatIndex = Math.round(timeInSeconds * beatsPerSecond);
return beatIndex * secondsPerBeat;
}
// Visual beat markers
for (let beat = 0; beat < maxBeats; beat++) {
const beatTime = beat * secondsPerBeat;
// Render subtle vertical line at beatTime
}
```
**UI Additions:**
- Checkbox: "☑️ Snap to Beat (S)" in zoom controls
- Display: "BPM: 120 | Beat: 0.5s" in status bar
- Visual: Dashed vertical lines at beat boundaries
**Effort:** 4-6 hours
**Dependencies:** None
**Impact:** Makes musical timing much easier
---
### 1.2 Create New Effects ⭐ Priority: HIGH
**Goal:** Add effects to sequences without manual property editing.
**Features:**
- "➕ Add Effect" button (enabled when sequence is selected)
- Modal dialog or inline form for effect creation:
- Effect class name (dropdown or autocomplete)
- Start time (relative to sequence)
- Duration
- Priority (default: 0)
- Constructor arguments (optional text field)
- Double-click on sequence to add effect at that position
- Right-click context menu option
**Implementation Details:**
```javascript
function showEffectCreationDialog(sequenceIndex, timeHint = 0) {
const dialog = document.createElement('div');
dialog.className = 'modal-dialog';
dialog.innerHTML = `
<h3>New Effect</h3>
<label>Class Name: <input id="newEffectClass" list="effectClasses"></label>
<datalist id="effectClasses">
<option>FlashEffect</option>
<option>FadeEffect</option>
<option>HeptagonEffect</option>
<!-- Add more from known effects -->
</datalist>
<label>Start Time: <input type="number" id="newEffectStart" value="${timeHint}"></label>
<label>Duration: <input type="number" id="newEffectDuration" value="1.0"></label>
<label>Priority: <input type="number" id="newEffectPriority" value="0"></label>
<label>Arguments: <input type="text" id="newEffectArgs"></label>
<button onclick="createEffect()">Create</button>
<button onclick="closeDialog()">Cancel</button>
`;
document.body.appendChild(dialog);
}
function createEffect() {
const effect = {
type: 'effect',
className: document.getElementById('newEffectClass').value,
startTime: parseFloat(document.getElementById('newEffectStart').value),
endTime: parseFloat(document.getElementById('newEffectStart').value) +
parseFloat(document.getElementById('newEffectDuration').value),
priority: parseInt(document.getElementById('newEffectPriority').value),
args: document.getElementById('newEffectArgs').value
};
sequences[selectedSequenceIndex].effects.push(effect);
closeDialog();
renderTimeline();
}
```
**UI Additions:**
- Button: "➕ Add Effect to Sequence" (appears when sequence selected)
- Modal dialog with form
- Context menu on right-click
- Keyboard shortcut: `E` key when sequence selected
**Effort:** 6-8 hours
**Dependencies:** Need list of available effect classes
**Impact:** Essential for productive editing
---
### 1.2b Priority Editing UI ⭐ Priority: HIGH
**Goal:** Enable visual editing of sequence and effect priorities.
**Features:**
- **Sequence Priority**: Edit absolute priority (0-9 for scene, 10+ for post-processing)
- **Effect Priority Modifier**: Toggle between `+`, `=`, `-` modifiers
- **Visual Priority Indicators**: Color-code or label items by priority level
- **Z-order visualization**: Show stacking order visually
**UI Design:**
**For Sequences:**
```
Properties Panel:
┌─────────────────────────────┐
│ Sequence Priority │
│ ┌─────────────────────────┐ │
│ │ Priority: [0] ▲▼ │ │
│ └─────────────────────────┘ │
│ (0-9: Scene, 10+: Post-FX) │
└─────────────────────────────┘
Visual indicator on timeline:
[0] Sequence 1 (dark blue)
[1] Sequence 2 (medium blue)
[5] Sequence 3 (light blue)
```
**For Effects:**
```
Properties Panel:
┌─────────────────────────────┐
│ Effect Priority Modifier │
│ ┌─────────────────────────┐ │
│ │ ○ + Increment (normal) │ │
│ │ ○ = Same as previous │ │
│ │ ● - Decrement (bg) │ │
│ └─────────────────────────┘ │
│ Computed priority: -1 │
└─────────────────────────────┘
Visual indicator on timeline:
[-1] FlashCubeEffect (darker gray, background)
[0] FlashEffect (normal gray)
[1] FadeEffect (lighter gray)
```
**Implementation:**
```javascript
// Sequence priority editor
function renderSequencePriorityEditor(seq) {
return `
<div class="property-group">
<label>Sequence Priority</label>
<div class="priority-control">
<input type="number" id="seqPriority" value="${seq.priority}"
min="0" max="20" step="1">
<button onclick="adjustPriority(-1)">▼</button>
<button onclick="adjustPriority(+1)">▲</button>
</div>
<small>0-9: Scene effects | 10+: Post-processing</small>
</div>
`;
}
// Effect priority modifier editor
function renderEffectPriorityEditor(effect) {
return `
<div class="property-group">
<label>Priority Modifier</label>
<div class="priority-modifier-group">
<label>
<input type="radio" name="priorityMod" value="+"
${effect.priorityModifier === '+' ? 'checked' : ''}>
+ Increment (normal)
</label>
<label>
<input type="radio" name="priorityMod" value="="
${effect.priorityModifier === '=' ? 'checked' : ''}>
= Same as previous
</label>
<label>
<input type="radio" name="priorityMod" value="-"
${effect.priorityModifier === '-' ? 'checked' : ''}>
- Decrement (background)
</label>
</div>
<small>Computed priority: ${effect.priority}</small>
</div>
`;
}
// Recalculate effect priorities after modifier change
function recalculatePriorities(sequence) {
let currentPriority = -1;
for (const effect of sequence.effects) {
if (effect.priorityModifier === '+') currentPriority++;
else if (effect.priorityModifier === '-') currentPriority--;
// '=' keeps current priority
effect.priority = currentPriority;
}
}
```
**Visual Priority Indicators (CSS):**
```css
/* Sequence priority colors */
.sequence[data-priority="0"] { border-color: #264f78; } /* Dark blue */
.sequence[data-priority="1"] { border-color: #0e639c; } /* Medium blue */
.sequence[data-priority="2"] { border-color: #1177bb; } /* Light blue */
/* Effect priority badge */
.effect::before {
content: "[" attr(data-priority) "]";
position: absolute;
top: 2px;
left: 2px;
font-size: 10px;
background: rgba(0,0,0,0.5);
padding: 2px 4px;
border-radius: 2px;
}
/* Background effects (negative priority) */
.effect[data-priority^="-"] {
opacity: 0.7;
background: #2d2d30;
}
```
**Validation:**
- Warn if sequence priorities conflict (same time + same priority)
- Show warning if effect priority order doesn't match visual stacking
- Suggest reordering effects if priority sequence is non-contiguous
**Effort:** 6-8 hours
**Priority:** HIGH (essential for proper z-order control)
**Dependencies:** None
**Impact:** Enables precise control over render order
---
### 1.3 Overlap Detection & Warnings ⭐ Priority: MEDIUM
**Goal:** Visualize and warn about timeline conflicts.
**Features:**
- Detect sequence overlaps (same priority, overlapping time ranges)
- Detect effect overlaps within same sequence
- Visual indicators:
- Red border around overlapping items
- Warning icon (⚠️) on overlapping items
- Tooltip explaining conflict
- Warnings panel listing all conflicts
- Filter timeline to show only conflicts
**Detection Logic:**
```javascript
function detectOverlaps() {
const conflicts = [];
// Check sequence overlaps (same priority)
for (let i = 0; i < sequences.length; i++) {
for (let j = i + 1; j < sequences.length; j++) {
const seq1 = sequences[i];
const seq2 = sequences[j];
if (seq1.priority !== seq2.priority) continue;
const seq1End = seq1.startTime + getSequenceDuration(seq1);
const seq2End = seq2.startTime + getSequenceDuration(seq2);
if (seq1.startTime < seq2End && seq2.startTime < seq1End) {
conflicts.push({
type: 'sequence',
items: [i, j],
severity: 'warning',
message: `Sequences ${i+1} and ${j+1} overlap with same priority ${seq1.priority}`
});
}
}
}
// Check effect overlaps within sequences
sequences.forEach((seq, seqIdx) => {
for (let i = 0; i < seq.effects.length; i++) {
for (let j = i + 1; j < seq.effects.length; j++) {
const eff1 = seq.effects[i];
const eff2 = seq.effects[j];
if (eff1.priority !== eff2.priority) continue;
if (eff1.startTime < eff2.endTime && eff2.startTime < eff1.endTime) {
conflicts.push({
type: 'effect',
sequenceIndex: seqIdx,
items: [i, j],
severity: 'info',
message: `Effects overlap in sequence ${seqIdx+1}`
});
}
}
}
});
return conflicts;
}
```
**Visual Indicators:**
```css
.sequence.conflict {
border-color: #f48771;
box-shadow: 0 0 10px rgba(244, 135, 113, 0.5);
}
.effect.conflict {
border-color: #f48771;
}
.conflict-warning {
position: absolute;
top: 2px;
right: 2px;
font-size: 14px;
}
```
**UI Additions:**
- Panel: "⚠️ Conflicts" (collapsible, shows list of warnings)
- Button: "🔍 Show Only Conflicts" (filters view)
- Visual: Red borders and warning icons on conflicting items
- Tooltip: Hover over warning icon for details
**Effort:** 8-10 hours
**Dependencies:** None
**Impact:** Prevents rendering issues and z-order bugs
---
## Phase 2: Productivity Enhancements (Medium Priority)
### 2.1 Undo/Redo System
**Goal:** Allow users to experiment without fear of breaking things.
**Implementation:**
- Command pattern for all mutations
- History stack (max 50 commands)
- Keyboard shortcuts: `Ctrl+Z` (undo), `Ctrl+Shift+Z` (redo)
- Buttons in toolbar
**Effort:** 10-12 hours
**Priority:** MEDIUM
---
### 2.2 Multi-Select & Batch Operations
**Goal:** Edit multiple items at once.
**Features:**
- Click + Ctrl/Cmd to add to selection
- Click + Shift for range selection
- Drag box to select multiple
- Batch operations:
- Move all selected items together
- Delete all selected
- Adjust priority of all selected
- Duplicate selection
**Effort:** 12-15 hours
**Priority:** MEDIUM
---
### 2.3 Copy/Paste & Duplication
**Goal:** Reuse sequences and effects quickly.
**Features:**
- `Ctrl+C` to copy selected item(s)
- `Ctrl+V` to paste at current time
- `Ctrl+D` to duplicate in place
- Paste adjusts timing to avoid overlaps (optional)
**Effort:** 6-8 hours
**Priority:** MEDIUM
---
### 2.4 Keyboard Shortcuts & Navigation
**Goal:** Power users can work without mouse.
**Shortcuts:**
- `Space`: Play/pause preview indicator (if implemented)
- `Arrow Keys`: Move selected item (fine adjustment)
- `Shift+Arrow`: Resize selected effect duration
- `Delete` / `Backspace`: Delete selected
- `S`: Toggle snap-to-beat
- `E`: Create effect in selected sequence
- `N`: New sequence
- `1-9`: Jump to sequence 1-9
- `/`: Focus search/filter box
**Effort:** 4-6 hours
**Priority:** MEDIUM
---
### 2.5 Music.track Visualization & Overlay
**Goal:** Display tracker patterns and samples alongside timeline for precise alignment.
**Features:**
- Load `music.track` file (parse tracker score format)
- Render tracker patterns as horizontal bars above/below sequences
- Display sample triggers (kick, snare, bass notes) as vertical markers
- Color-code different sample types (drums, bass, melody)
- Show pattern names and beat divisions
- Toggle visibility (checkbox: "Show Tracker Score")
- Sync horizontal scale with timeline (pixels per second)
- Help users align visual sequences with audio events
**Implementation Details:**
```javascript
// Parse music.track file format (similar to demo.seq parser)
function parseTrackerScore(content) {
// Extract patterns, events, sample triggers
// Return structured data: { patterns: [...], events: [...] }
}
// Render tracker overlay on canvas or DOM elements
function renderTrackerOverlay() {
// Draw pattern bars
// Draw sample trigger markers (vertical lines)
// Label with sample names (KICK_1, BASS_E2, etc.)
}
```
**Visual Design:**
- Tracker patterns: Semi-transparent colored bars (green/yellow/purple)
- Sample triggers: Thin vertical lines with labels
- Pattern names: Small text above bars
- Positioned above waveform, below time markers
**Use Case:**
- Load `music.track` to see exactly where drums/bass/melody trigger
- Align visual effect sequences with musical events
- Verify timing matches tracker score before testing in demo
**Effort:** 12-15 hours
**Priority:** MEDIUM
**Dependencies:** Requires `music.track` file format specification
---
## Phase 3: Advanced Features (Low Priority)
### 3.1 Timeline Playback Indicator
**Goal:** Visualize current playback position.
**Features:**
- Vertical red line showing current time
- Play/pause button
- Time advances at real-time speed (or adjustable)
- Click timeline to seek
- Does NOT render effects (just shows position)
**Effort:** 4-6 hours
**Priority:** LOW
**Note:** This is ONLY a position indicator, not a preview renderer
---
### 3.2 Templates & Presets
**Goal:** Quick-start with common patterns.
**Features:**
- Template library (e.g., "Intro Sequence", "Beat Drop", "Outro")
- Save custom templates
- Drag template onto timeline to instantiate
- Templates include sequences + effects with relative timing
**Effort:** 8-10 hours
**Priority:** LOW
---
### 3.3 Search & Filter
**Goal:** Navigate large timelines quickly.
**Features:**
- Search bar: Filter by effect class name
- Filter by priority
- Filter by time range
- Highlight matching items
- "Go to" dialog (jump to specific time)
**Effort:** 6-8 hours
**Priority:** LOW
---
### 3.4 Timeline Comparison View
**Goal:** Compare two versions of the timeline.
**Features:**
- Load two .seq files side by side
- Diff view showing additions/deletions/changes
- Color-coded: green = added, red = removed, yellow = modified
- Merge changes from one timeline to another
**Effort:** 15-20 hours
**Priority:** LOW
---
### 3.5 Export Formats
**Goal:** Support alternative output formats.
**Features:**
- Export to JSON (for programmatic processing)
- Export to CSV (for spreadsheet analysis)
- Export to Markdown table (for documentation)
- Import from JSON/CSV
**Effort:** 6-8 hours
**Priority:** LOW
---
### 3.6 Auto-Save & Local Storage
**Goal:** Never lose work.
**Features:**
- Auto-save to browser localStorage every 30 seconds
- Restore last session on load
- Warning if leaving page with unsaved changes
- Session history (last 5 sessions)
**Effort:** 4-6 hours
**Priority:** LOW
---
## Implementation Priority
**Immediate (Next 1-2 weeks):**
1. ✅ Snap-to-Beat (4-6h) - Makes editing much easier
2. ✅ Create New Effects (6-8h) - Essential for productivity
3. ✅ Priority Editing UI (6-8h) - Essential for z-order control
**Short-term (Next 1-2 months):**
4. ✅ Overlap Detection (8-10h) - Prevents bugs
5. ✅ Undo/Redo (10-12h) - Safety net for experimentation
6. ✅ Copy/Paste (6-8h) - Common workflow
**Medium-term (Next 3-6 months):**
6. Multi-Select (12-15h)
7. Keyboard Shortcuts (4-6h)
8. Timeline Playback Indicator (4-6h)
**Long-term (Nice to have):**
9. Templates (8-10h)
10. Search/Filter (6-8h)
11. Timeline Comparison (15-20h)
12. Export Formats (6-8h)
13. Auto-Save (4-6h)
---
## Total Effort Estimates
**Phase 1 (Core):** 28-36 hours (was 22-28, added priority editing)
**Phase 2 (Productivity):** 38-51 hours
**Phase 3 (Advanced):** 51-74 hours
**Total:** ~117-161 hours for full feature set
---
## Development Approach
**Incremental Rollout:**
- Each feature should be a separate commit
- Keep the single-file HTML structure for simplicity
- Add features in priority order
- Test with real demo.seq files after each feature
**Code Organization (when file gets too large):**
- Consider splitting into:
- `index.html` (UI structure + styles)
- `editor.js` (main logic)
- `parser.js` (seq file parsing)
- `timeline.js` (rendering)
- `commands.js` (undo/redo system)
**Testing Strategy:**
- Manual testing with assets/demo.seq
- Test edge cases: empty files, single sequence, many overlaps
- Browser compatibility: Chrome, Firefox, Safari
- No automated tests (keep it simple for now)
---
## Design Principles
1. **Keep it simple:** Avoid over-engineering
2. **No dependencies:** Stay pure HTML/JS/CSS
3. **Instant feedback:** All operations should feel immediate
4. **Visual clarity:** Color-coding, icons, clear labels
5. **Forgiving UX:** Undo/redo, non-destructive operations
6. **Offline-first:** No network required
---
## Questions for Future Consideration
1. **Effect Class Validation:**
- Should we validate effect class names against known effects?
- Source of truth: Parse C++ code? Hardcoded list? User-maintained?
2. **Priority System:**
- Current system uses integers (-1, 0, 1, 2...)
- Should we add named priority levels? (Background, Normal, Foreground, Top)
3. **BPM Changes:**
- What if BPM changes mid-timeline?
- Support for tempo changes?
4. **Collaboration:**
- Should multiple people be able to edit the same timeline?
- Real-time collaboration? (probably overkill)
5. **Preview Integration:**
- Should we ever integrate visual preview?
- Current answer: NO (out of scope, would require WebAssembly + full engine)
---
## Success Metrics
**v1.0 (Current):** ✅ Basic editing works
**v1.1 (Phase 1):** Snap-to-beat + effect creation = productive editing
**v2.0 (Phase 2):** Undo/redo + multi-select = professional tool
**v3.0 (Phase 3):** Advanced features = power user delight
**Goal:** Make timeline editing 10x faster than manual text editing.
|