| Age | Commit message (Collapse) | Author |
|
MILESTONE: Spectral Brush Editor Phase 2 Complete (February 6, 2026)
Phase 2 delivers a production-ready web-based editor for creating procedural
audio by tracing spectrograms with parametric Bezier curves. This tool enables
replacing 5KB .spec binary assets with ~100 bytes of C++ code (50-100× compression).
Core Features Implemented:
========================
Audio I/O:
- Load .wav and .spec files as reference spectrograms
- Real-time audio preview (procedural vs original)
- Live volume control with GainNode (updates during playback)
- Export to procedural_params.txt (human-readable, re-editable format)
- Generate C++ code (copy-paste ready for demo integration)
Curve Editing:
- Multi-curve support with individual colors and volumes
- Bezier curve control points (frame, frequency, amplitude)
- Drag-and-drop control point editing
- Per-curve volume control (0-100%)
- Right-click to delete control points
- Curves only render within control point range (no spill)
Profile System (All 3 types implemented):
- Gaussian: exp(-(dist² / σ²)) - smooth harmonic falloff
- Decaying Sinusoid: exp(-decay × dist) × cos(ω × dist) - metallic resonance
- Noise: noise × exp(-(dist² / decay²)) - textured grit with decay envelope
Visualization:
- Log-scale frequency axis (20 Hz to 16 kHz) for better bass visibility
- Logarithmic dB-scale intensity mapping (-60 dB to +40 dB range)
- Reference opacity slider (0-100%) for mixing original/procedural views
- Playhead indicator (red dashed line) during playback
- Mouse crosshair with tooltip (frame number, frequency)
- Control point info panel (frame, frequency, amplitude)
Real-time Spectrum Viewer (NEW):
- Always-visible bottom-right overlay (200×100px)
- Shows frequency spectrum for frame under mouse (hover mode)
- Shows current playback frame spectrum (playback mode)
- Dual display: Reference (green) + Procedural (red) overlaid
- dB-scale bar heights for accurate visualization
- Frame number label (red during playback, gray when hovering)
Rendering Architecture:
- Destination-to-source pixel mapping (prevents gaps in log-scale)
- Offscreen canvas compositing for proper alpha blending
- Alpha channel for procedural intensity (pure colors, not dimmed)
- Steeper dB falloff for procedural curves (-40 dB floor vs -60 dB reference)
UI/UX:
- Undo/Redo system (50-action history)
- Keyboard shortcuts (1/2/Space for playback, Ctrl+Z/Ctrl+Shift+Z, Delete, Esc)
- File load confirmation (warns about unsaved curves)
- Automatic curve reset on new file load
Technical Details:
- DCT/IDCT implementation (JavaScript port matching C++ runtime)
- Overlap-add synthesis with Hanning window
- Web Audio API integration (32 kHz sample rate)
- Zero external dependencies (pure HTML/CSS/JS)
Files Modified:
- tools/spectral_editor/script.js (~1730 lines, main implementation)
- tools/spectral_editor/index.html (UI structure, spectrum viewer)
- tools/spectral_editor/style.css (VSCode dark theme styling)
- tools/spectral_editor/README.md (updated features, roadmap)
Phase 3 TODO (Next):
===================
- Effect combination system (noise + Gaussian modulation, layer compositing)
- Improved C++ code testing (validation, edge cases)
- Better frequency scale (mu-law or perceptual scale, less bass-heavy)
- Pre-defined shape library (kick, snare, hi-hat templates)
- Load procedural_params.txt back into editor (re-editing)
- FFT-based DCT optimization (O(N log N) vs O(N²))
Integration:
- Generate C++ code → Copy to src/audio/procedural_samples.cc
- Add PROC() entry to assets/final/demo_assets.txt
- Rebuild demo → Use AssetId::SOUND_PROC
handoff(Claude): Phase 2 complete. Next: FFT implementation task for performance optimization.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
|
Fixed three issues reported during testing:
1. Procedural audio now audible:
- Added AMPLITUDE_SCALE=10.0 to match DCT coefficient magnitudes
- Amplitude range 0-1 from Y-position now scaled to proper spectral levels
2. Procedural spectrogram now visible:
- Each curve rendered separately with its own color
- Normalized intensity calculation (specValue / 10.0)
- Only draw pixels with intensity > 0.01 for performance
3. Color-coded curves:
- Each curve assigned unique color from palette (8 colors cycling)
- Colors: Blue, Green, Orange, Purple, Cyan, Brown, Pink, Gold
- Control points and paths use curve color
- Curve list shows color indicator dot
- Procedural spectrogram uses curve colors for easy tracking
Visual improvements:
- Selected curves have thicker stroke (3px vs 2px)
- Each curve contribution visible in separate color
- Color dots in sidebar for quick identification
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
|
Fixed 'Identifier source has already been declared' error at line 935.
Bug: Function parameter 'source' (string: 'procedural' or 'original')
conflicted with local AudioBufferSourceNode variable.
Fix: Renamed local variable to 'bufferSource' for clarity.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
|
Implement web-based editor for procedural audio tracing.
New Files:
- tools/spectral_editor/index.html - Main UI structure
- tools/spectral_editor/style.css - VSCode-inspired dark theme
- tools/spectral_editor/script.js - Editor logic (~1200 lines)
- tools/spectral_editor/dct.js - IDCT/DCT implementation (reused)
- tools/spectral_editor/README.md - Complete user guide
Features:
- Dual-layer canvas (reference + procedural spectrograms)
- Bezier curve editor (click to place, drag to adjust, right-click to delete)
- Profile controls (Gaussian sigma slider)
- Real-time audio playback (Key 1=procedural, Key 2=original, Space=stop)
- Undo/Redo system (50-action history with snapshots)
- File I/O:
- Load .wav/.spec files (FFT/STFT or binary parser)
- Save procedural_params.txt (human-readable, re-editable)
- Generate C++ code (copy-paste ready for runtime)
- Keyboard shortcuts (Ctrl+Z/Shift+Z, Ctrl+S/Shift+S, Ctrl+O, ?)
- Help modal with shortcut reference
Technical:
- Pure HTML/CSS/JS (no dependencies)
- Web Audio API for playback (32 kHz sample rate)
- Canvas 2D for visualization (log-scale frequency)
- Linear Bezier interpolation matching C++ runtime
- IDCT with overlap-add synthesis
Next: Phase 3 (currently integrated in Phase 2)
- File loading already implemented
- Export already implemented
- Ready for user testing!
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
|
Implement C++ runtime foundation for procedural audio tracing tool.
Changes:
- Created spectral_brush.h/cc with core API
- Linear Bezier interpolation
- Vertical profile evaluation (Gaussian, Decaying Sinusoid, Noise)
- draw_bezier_curve() for spectrogram rendering
- Home-brew deterministic RNG for noise profile
- Added comprehensive unit tests (test_spectral_brush.cc)
- Tests Bezier interpolation, profiles, edge cases
- Tests full spectrogram rendering pipeline
- All 9 tests pass
- Integrated into CMake build system
- Fixed test_assets.cc include (asset_manager_utils.h)
Design:
- Spectral Brush = Central Curve (Bezier) + Vertical Profile
- Enables 50-100x compression (5KB .spec to 100 bytes C++ code)
- Future: Cubic Bezier, composite profiles, multi-dimensional curves
Documentation:
- Added doc/SPECTRAL_BRUSH_EDITOR.md (complete architecture)
- Updated TODO.md with Phase 1-4 implementation plan
- Updated PROJECT_CONTEXT.md to mark Task #5 in progress
Test results: 21/21 tests pass (100%)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
|
Updated documentation to reflect completed build system improvements:
TODO.md:
- Moved Task C to 'Recently Completed (February 6, 2026)' section
- Documented header split (asset_manager_dcl/core/utils)
- Documented asset dependency tracking (42 demo + 17 test assets)
- Noted 58% performance improvement and critical correctness bug fix
- Removed Task C from 'Critical Fixes' section (completed)
PROJECT_CONTEXT.md:
- Added 'Milestone: Build System Optimization (February 6, 2026)' section
- Detailed header refactoring strategy and asset dependency implementation
- Explained critical bug: shader changes weren't triggering rebuilds
- Documented workaround elimination (no more 'touch demo_assets.txt')
HOWTO.md:
- Added 'Build System Notes' section after developer build instructions
- Explained incremental build behavior and asset tracking
- Documented header organization (dcl/core/utils) for developers
- Clarified that all asset types (.wgsl, .spec, .obj) are tracked
All documentation now accurately reflects current build system state.
Ready to begin next task: Spectrogram Editor (HTML).
|
|
CRITICAL FIX: Changing .wgsl/.spec/.obj files now triggers asset regeneration.
Problem: CMake only tracked demo_assets.txt, not individual asset files.
Result: Editing shaders didn't trigger rebuilds → stale code in binary!
Solution: Parse demo_assets.txt to extract all asset filenames and add them
to DEPENDS clause in add_custom_command(). Now CMake tracks all 42 assets.
Implementation:
- Added parse_asset_list() function to extract filenames from asset list
- Regex parses format: ASSET_NAME, COMPRESSION, FILENAME, DESCRIPTION
- Filters out PROC() entries (procedural, no file on disk)
- Adds full paths to DEPENDS for both pack_assets() and pack_test_assets()
Performance impact:
- Before: touch shader → 0.28s (no rebuild, STALE!)
- After: touch shader → 3.55s (regenerates assets, rebuilds users)
Files tracked: 42 demo assets + 17 test assets
- Shaders: renderer_3d.wgsl, mesh_render.wgsl, skybox.wgsl, etc.
- Audio: kick1.spec, KICK_606.spec, snare samples, bass samples
- Meshes: dodecahedron.obj, other geometry
Developer workflow: No more 'touch demo_assets.txt' workaround needed!
Just edit shaders and rebuild - dependencies work correctly now.
|
|
Split monolithic asset_manager.h (61 lines) into 3 focused headers:
- asset_manager_dcl.h: Forward declarations (AssetId, ProcGenFunc)
- asset_manager.h: Core API (GetAsset, DropAsset, AssetRecord)
- asset_manager_utils.h: Typed helpers (TextureAsset, MeshAsset)
Updated 17 source files to use appropriate headers:
- object.h: Uses dcl.h (only needs AssetId forward declaration)
- 7 files using TextureAsset/MeshAsset: Use utils.h
- 10 files using only GetAsset(): Keep asset_manager.h
Performance improvement:
- Before: Touch asset_manager.h → 4.82s (35 files rebuild)
- After: Touch asset_manager_utils.h → 2.01s (24 files rebuild)
- Improvement: 58% faster for common workflow (tweaking mesh/texture helpers)
Note: Touching base headers (dcl/core) still triggers ~33 file rebuilds
due to object.h dependency chain. Further optimization would require
reducing object.h's footprint (separate task).
Files changed:
- Created: asset_manager_dcl.h, asset_manager_utils.h
- Modified: asset_manager.h (removed structs), asset_manager.cc
- Updated: object.h, visual_debug.h, renderer_mesh.cc,
flash_cube_effect.cc, hybrid_3d_effect.cc, test files
|
|
Task A progress:
✅ Mesh normal transformation fixed (shader double-transpose bug)
✅ Quaternion rotation stretching fixed (axis normalization)
✅ Mesh shadow scaling fixed (excluded from SDF scale factor)
✅ Floor rendering artifacts fixed (PLANE → BOX workaround)
Remaining issues:
- Task A.1: Missing shadows in test_mesh (needs investigation)
- Task A.2: ObjectType::PLANE broken with non-uniform scaling
- Root cause: sdPlane doesn't handle non-uniform scale in local space
- Workaround applied: Using BOX instead of PLANE for floor
- Need to determine if PLANE should support this or is unsupported by design
handoff(Claude): Test mesh visual artifacts resolved, but PLANE object type
has fundamental issues with non-uniform scaling. Workaround in place, but
proper fix requires deeper investigation into SDF distance field math.
|
|
The issue was using ObjectType::PLANE with extreme non-uniform scaling
(20, 0.01, 20) which causes incorrect SDF distance calculations in shadows.
Following the pattern from test_3d_render.cc (which works correctly),
changed the floor to use ObjectType::BOX with:
- Position: vec3(0, -2, 0) (placed below ground level)
- Scale: vec3(25, 0.2, 25) (thin box, not extreme ratio)
This provides a proper floor surface without the shadow artifacts caused
by PLANE's distance field distortion under non-uniform scaling.
|
|
This reverts commit a5229022b0e500ac86560e585081f45293e587d2.
|
|
When a plane has non-uniform scaling (e.g., floor with scale 20,0.01,20),
transforming points to local space distorts SDF distances. For a horizontal
plane with Y-scale of 0.01, distances become 100x too large in local space.
Fix: Multiply plane distances by the scale factor along the normal direction
(Y component for horizontal planes). This corrects shadow calculations while
maintaining the large floor area needed for visualization.
Reverted incorrect uniform scale fix (c23f3b9) that made floor too small.
|
|
This reverts commit b2bd45885a77e8936ab1d2c2ed30a238d9f073a6.
|
|
Fixed floor shadow stretching caused by extreme non-uniform scaling.
ROOT CAUSE:
Floor plane used scale(20.0, 0.01, 20.0) - a 2000:1 scale ratio!
When transforming shadow ray points into local space:
- Y coordinates scaled by 1/0.01 = 100x
- sdPlane distance calculation returns distorted values
- Shadow raymarching fails, causing stretching artifacts
ISSUE:
floor.scale = vec3(20.0f, 0.01f, 20.0f); // ❌ Extreme non-uniform scale
// In local space: dot(p_local, (0,1,0)) + 0.0
// But p_local.y is 100x larger than world-space distance!
FIX:
floor.scale = vec3(1.0f, 1.0f, 1.0f); // ✓ Uniform scale
floor.position = vec3(0, 0, 0); // Explicit ground level
EXPLANATION:
For PLANE objects, XZ scale doesn't matter (planes are infinite).
Y scale distorts the SDF distance calculation.
Uniform scale preserves correct world-space distances.
RESULT:
- Floor shadows now render correctly
- No stretching toward center
- Shadow distances accurate for soft shadow calculations
COMBINED WITH PREVIOUS FIXES:
1. Shader normal transformation (double-transpose fix)
2. Quaternion axis normalization (rotation stretching fix)
3. Mesh shadow scaling exclusion (AABB size fix)
4. Floor uniform scale (this fix)
Task A (test_mesh visualization) now FULLY RESOLVED.
handoff(Claude): All mesh transformation and shadow bugs fixed. Meshes
rotate correctly, normals transform properly, shadows render accurately.
Remaining known limitation: mesh shadows use AABB (axis-aligned), so
they don't rotate with the mesh - this is expected AABB behavior.
|
|
Fixed incorrect mesh shadow rendering caused by applying scale factor to
mesh AABBs which already have correct local-space extents.
ROOT CAUSE:
The 's' scale factor (line 44) is meant for UNIT primitives (sphere,
box, torus) that are scaled by the model matrix. Meshes (type 5.0)
already store their correct AABB extents in obj_params.yzw, so applying
's' caused incorrect shadow sizes.
ISSUE:
let s = min(length(obj.model[0].xyz), ...);
if (obj.params.x != 4.0) { // Excluded planes only
d = min(d, get_dist(q, obj.params) * s); // ❌ WRONG for meshes!
}
FIX:
if (obj.params.x != 4.0 && obj.params.x != 5.0) { // Exclude planes AND meshes
d = min(d, get_dist(q, obj.params) * s);
} else {
d = min(d, get_dist(q, obj.params)); // No scaling
}
EXPLANATION:
- Type 1.0 (Sphere): Unit sphere, scaled by 's' ✓
- Type 2.0 (Box): Unit box, scaled by 's' ✓
- Type 3.0 (Torus): Unit torus, scaled by 's' ✓
- Type 4.0 (Plane): Special case, no scaling ✓
- Type 5.0 (Mesh): AABB already has correct size, no scaling needed ✓
FILES FIXED:
- assets/final/shaders/render/scene_query_linear.wgsl
- assets/final/shaders/render/scene_query_bvh.wgsl
PARTIAL FIX:
This fixes mesh shadow sizing issues. Shadow rotation limitation remains
(AABBs are axis-aligned, don't rotate with mesh - this is a fundamental
AABB limitation, not a bug).
handoff(Claude): Mesh shadows now correctly sized. Investigating floor
shadow stretching issue next (likely related to plane scaling).
|
|
Fixed critical bug causing mesh and bounding box stretching during rotation.
ROOT CAUSE:
quat::from_axis() did not normalize the input axis vector. When called
with non-unit vectors (e.g., {0.5, 1.0, 0.0}), it created invalid
quaternions that encoded scaling transformations instead of pure rotations.
SYMPTOMS:
- Mesh vertices stretched during rotation (non-uniform scaling)
- Bounding boxes deformed and stretched
- Transform matrices became non-orthogonal
ISSUE LOCATIONS:
- src/tests/test_mesh.cc:309 - axis {0.5, 1.0, 0.0} (length ≈1.118)
- src/gpu/effects/flash_cube_effect.cc:79 - axis {0.3, 1, 0.2} (length ≈1.044)
FIX:
Added automatic normalization in quat::from_axis():
a = a.normalize(); // Ensure axis is unit vector
RESULT:
- All quaternions now represent pure rotations
- No scaling artifacts during rotation
- Bounding boxes remain orthogonal
- Fixes Task A (test_mesh stretching bug)
SAFETY:
This change is backward compatible. Code that already passed normalized
axes will work identically (normalizing a unit vector = identity).
handoff(Claude): Rotation stretching bug fixed. Both shader normal
transformation (previous commit) and quaternion creation (this commit)
now work correctly. test_mesh should display properly rotated meshes
without distortion.
|
|
Fixed critical bug in normal matrix transformation causing mesh stretching
and incorrect scaling during rotation.
ROOT CAUSE:
In WGSL, mat3x3(v0, v1, v2) creates a matrix where v0, v1, v2 are COLUMNS.
When extracting rows from inv_model, the constructor already produces the
transpose. Applying transpose() again cancels out, giving incorrect normals.
ISSUE:
let normal_matrix = mat3x3(inv_model[0].xyz, inv_model[1].xyz, inv_model[2].xyz);
// This gives transpose(inv_model) already!
out.normal = normalize(transpose(normal_matrix) * in.normal);
// Double transpose = identity, wrong result
FIX:
let normal_matrix = mat3x3(inv_model[0].xyz, inv_model[1].xyz, inv_model[2].xyz);
// Already transpose(inv_model), which is the correct normal matrix
out.normal = normalize(normal_matrix * in.normal);
// Correct transformation
FILES FIXED:
- assets/final/shaders/mesh_render.wgsl:38 (mesh vertex normals)
- assets/final/shaders/renderer_3d.wgsl:185 (SDF bump-mapped normals)
RESULT:
Mesh normals now transform correctly under rotation and non-uniform scaling.
Fixes Task A (test_mesh visualization stretching bug).
handoff(Claude): Normal transformation bug fixed. Mesh should now render
correctly without stretching. Shadow bug on floor plane still remains
(separate WGSL shader issue for later investigation).
|
|
|
|
Updated PROJECT_CONTEXT.md and TODO.md to include new critical tasks and reflect changes in task prioritization.
Modified doc/3D.md to adjust task descriptions.
Modified doc/CONTRIBUTING.md to incorporate the new in-memory replacement rule.
Regenerated asset files (src/generated/assets.h, src/generated/assets_data.cc, src/generated/test_assets.h, src/generated/test_assets_data.cc) to reflect any changes in asset definitions.
Removed temporary changes to GEMINI.md and HANDOFF.md.
|
|
- Rewrote WGPU asynchronous initialization in test_mesh.cc to align with current wgpu-native API on macOS, including correct callback signatures and userdata handling.
- Replaced std::this_thread::sleep_for with platform_wgpu_wait_any for proper WGPU event processing.
- Corrected static method call for Renderer3D::SetDebugEnabled.
- Updated WGPUSurfaceGetCurrentTextureStatus_Success to WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal.
- Removed fprintf calls from WGPU callbacks to avoid WGPUStringView::s member access issues.
- Ensured a clean build and successful execution of test_mesh on macOS.
|
|
Implemented a new standalone test tool 'test_mesh' to:
- Load a .obj file specified via command line.
- Display the mesh with rotation and basic lighting on a tiled floor.
- Provide a '--debug' option to visualize vertex normals as cyan lines.
- Updated asset_packer to auto-generate smooth normals for OBJs if missing.
- Fixed various WGPU API usage inconsistencies and build issues on macOS.
- Exposed Renderer3D::GetVisualDebug() for test access.
- Added custom Vec3 struct and math utilities for OBJ parsing.
This tool helps verify mesh ingestion and normal computation independently of the main demo logic.
|
|
Updated asset_packer to detect missing normals in OBJ files.
Implemented a 2-pass parser:
1. Read geometry and connectivity.
2. If normals are missing:
- Compute face normals using cross product.
- Accumulate and average normals per vertex (Smooth Shading).
- Update face indices to map normals 1:1 with positions.
This fixes the 'no shading' issue for assets like dodecahedron.obj which lack normals.
|
|
Added dodecahedron.obj (downloaded from external source) to demo assets.
Updated test_3d_render to display the dodecahedron mesh alongside the cube mesh.
Verified asset packing and rendering pipeline.
|
|
Moved SDF, Mesh, and Skybox logic into separate files to adhere to the 500-line file limit rule.
- src/3d/renderer_sdf.cc
- src/3d/renderer_mesh.cc
- src/3d/renderer_skybox.cc
|
|
Added support for loading and rendering OBJ meshes.
- Updated asset_packer to parse .obj files into a binary format.
- Added MeshAsset and GetMeshAsset helper to asset_manager.
- Extended Object3D with mesh_asset_id and ObjectType::MESH.
- Implemented mesh rasterization pipeline in Renderer3D.
- Added a sample cube mesh and verified in test_3d_render.
|
|
Removed obsolete scene_query.wgsl (replaced by variants). Updated TODO.md. Committed generated asset files reflecting new shader snippets.
|
|
Completed Task #18-B optimization and refactoring.
- Replaced runtime branching in shader with compile-time snippet substitution in ShaderComposer.
- Added 'scene_query_bvh.wgsl' and 'scene_query_linear.wgsl' as distinct snippets.
- Refactored Renderer3D to manage two separate pipelines (with and without BVH).
- Updated ShaderComposer to support snippet substitution during composition.
- Verified both paths with test_3d_render (default and --no-bvh).
- Removed temporary shader hacks and cleaned up renderer_3d.wgsl.
|
|
Completed Task #18-B.
- Implemented GPU-side BVH traversal for scene queries, improving performance.
- Added a --no-bvh command-line flag to disable the feature for debugging and performance comparison.
- Fixed a shader compilation issue where the non-BVH fallback path failed to render objects.
|
|
═══════════════════════════════════════════════════════════════════
🎉 MILESTONE: Interactive Timeline Editor - Phase 1 Complete 🎉
═══════════════════════════════════════════════════════════════════
Task #57 Phase 1 delivers a fully functional web-based timeline editor
for demo.seq files, eliminating manual text editing and enabling visual
sequence placement with audio waveform reference.
───────────────────────────────────────────────────────────────────
IMPLEMENTED FEATURES (Phase 1.1)
───────────────────────────────────────────────────────────────────
Core Editing:
✅ Load/save demo.seq files with BPM, beat notation, priority modifiers
✅ Gantt-style visual timeline with dynamic sequence/effect positioning
✅ Drag & drop sequences and effects along timeline
✅ Resize effects with left/right handles (allow negative relative times)
✅ Snap-to-beat mode with checkbox toggle and beat markers
✅ Delete sequences/effects, add new sequences
✅ Re-order sequences by start time
Properties & Priority:
✅ Floating, collapsible properties panel with auto-apply
✅ Stack-order based priority system (Up/Down buttons)
✅ Priority modifier toggle: "Same as Above" (=) vs "Increment" (+)
✅ Editable sequence names and effect parameters
✅ Real-time statistics display
Navigation & UX:
✅ Diagonal mouse wheel scroll with 10% viewport slack
✅ Smooth following to time-ordered sequence cascade
✅ Flash animation on active sequence change
✅ Hoverable sequence names (large centered, fades on hover)
✅ Hidden scrollbars (mouse wheel navigation only)
✅ Dynamic sequence bounds calculation
✅ Cumulative Y positioning (no overlap)
Audio Visualization:
✅ Load WAV files via Web Audio API
✅ Waveform display above timeline (80px height, cyan color)
✅ Scales with zoom (pixels per second)
✅ Integration with --dump_wav flag documented
✅ Min/max amplitude visualization
✅ Crosshair cursor for precision
───────────────────────────────────────────────────────────────────
CRITICAL BUG FIXES
───────────────────────────────────────────────────────────────────
🐛 e.target vs e.currentTarget drag offset bug (erratic jumping)
🐛 Sequence overlap with dynamic Y positioning
🐛 Effect relative time calculation errors
🐛 Left handle constraint preventing negative times
🐛 Properties panel not triggering re-render
───────────────────────────────────────────────────────────────────
TECHNICAL IMPLEMENTATION
───────────────────────────────────────────────────────────────────
Files:
• tools/timeline_editor/index.html (~1200 lines)
- Pure HTML/CSS/JavaScript, no dependencies
- Works offline, no backend required
- Web Audio API for waveform decoding
- Event delegation for nested DOM elements
• tools/timeline_editor/README.md
- Usage guide and keyboard shortcuts
- WAV file generation with --dump_wav integration
- Format specification reference (doc/SEQUENCE.md)
• tools/timeline_editor/ROADMAP.md
- 3-phase development plan (117-161 hour estimate)
- Phase 1.2: Add Effect button (next priority)
- Phase 2.5: music.track visualization overlay
Key Patterns:
• Effect times stored RELATIVE to parent sequence startTime
• Sequence visual bounds calculated from min/max effect times
• Stack order determines priority (array index)
• Snap-to-beat: Math.round(time / beatDuration) * beatDuration
• Dynamic cumulative Y positioning prevents overlap
• e.currentTarget vs e.target for proper event delegation
───────────────────────────────────────────────────────────────────
DOCUMENTATION UPDATES
───────────────────────────────────────────────────────────────────
TODO.md:
• Added Task #57 to Recently Completed section
• Comprehensive feature list and bug fix summary
PROJECT_CONTEXT.md:
• Added Milestone: Interactive Timeline Editor (February 5, 2026)
• Documented integration with --dump_wav workflow
• Next steps: Phase 1.2 and Phase 2.5
───────────────────────────────────────────────────────────────────
NEXT STEPS
───────────────────────────────────────────────────────────────────
Phase 1.2: Add Effect Button (Priority: HIGH)
- Create effects within sequences via UI
- Modal dialog for effect class/timing/args
Phase 2.5: Music.track Visualization (Priority: MEDIUM)
- Parse music.track file format
- Overlay tracker patterns/samples on timeline
- Align visual sequences with audio events
───────────────────────────────────────────────────────────────────
IMPACT
───────────────────────────────────────────────────────────────────
✨ Visual timeline editing now production-ready
✨ Eliminates manual text editing for sequence placement
✨ WAV waveform integration enables precise audio-visual alignment
✨ Snap-to-beat ensures musical timing accuracy
✨ Stack-order priority system simplifies effect layering
───────────────────────────────────────────────────────────────────
handoff(Claude): Timeline editor Phase 1 milestone complete. All core
editing features working correctly. Waveform visualization integrated
with --dump_wav workflow. Ready for Phase 1.2 (Add Effect button) or
Phase 2 productivity enhancements (undo/redo, multi-select, templates).
No known bugs. Production-ready for demo.seq editing workflow.
|
|
Updated documentation:
README.md:
- Added waveform visualization to implemented features list
- Added section on loading audio waveform with usage instructions
- Documented wav_dump_backend integration: ./demo64k --dump_wav output.wav
- Added snap-to-beat and resize handles to feature list
- Updated Future Enhancements with music.track visualization
ROADMAP.md:
- Added Phase 2.5: Music.track Visualization & Overlay
- Detailed implementation plan for tracker score overlay
- Visual design specifications (colored bars, sample markers)
- Use case: Align visual sequences with tracker events
- Effort: 12-15 hours, Priority: MEDIUM
The timeline editor now has clear guidance on:
1. How to generate WAV files from demo64k for visual reference
2. Future feature: Display tracker patterns/samples for alignment
|
|
Added audio waveform feature for visual reference when placing sequences:
Features:
- Load Audio (WAV) button to upload audio files
- Waveform canvas displayed above timeline with 80px height
- Waveform scales with zoom (pixels per second)
- Auto-extends timeline to fit audio duration
- Clear Audio button to remove waveform
- Waveform uses Web Audio API for decoding
- Min/max amplitude visualization for better clarity
- Semi-transparent background with center line
UI:
- Waveform positioned above time markers
- Crosshair cursor for precision
- Cyan (#4ec9b0) waveform color matching editor theme
- Scrolls horizontally with timeline
No audio playback - visualization only for sequence placement assistance.
|
|
Added CSS to hide scrollbars on timeline container:
- scrollbar-width: none (Firefox)
- -ms-overflow-style: none (IE/Edge)
- ::-webkit-scrollbar { display: none } (Chrome/Safari/Opera)
Mouse wheel navigation still works, cleaner UI without visible scrollbars.
|
|
Implemented final UI improvements:
- Removed sequence info text (Start:, Priority)
- Removed 'Properties updated' message
- Auto-apply properties with oninput handlers
- Stack-order-based priority with Up/Down buttons
- Added 'Same as Above' toggle for = priority modifier
New functions: autoApplyProperties(), moveEffectUp(), moveEffectDown(), toggleSamePriority()
Task #57 Phase 1 complete: Interactive editor with drag-drop, resize handles, snap-to-beat, and stack-based priority.
handoff(Claude): Timeline editor Phase 1 feature-complete. All dragging bugs fixed, dynamic bounds working, stack-order priority operational. Ready for Phase 2 planning.
|
|
CRITICAL BUG FIX: Effect Start Time Jumping
Root Cause:
Line 788: const currentLeft = parseFloat(e.target.style.left) || 0;
Problem: e.target is what was CLICKED, not what has the listener
- Clicking effect div itself: e.target = effectDiv ✓
- Clicking <small> text inside: e.target = <small> ✗
- If e.target is <small>, it has no style.left property
- parseFloat(undefined) returns NaN, || 0 gives 0
- Wrong offset calculation → effect jumps on click!
The Fix:
Use e.currentTarget instead of e.target
- currentTarget = element with the event listener (always effectDiv)
- target = element that was actually clicked (could be child)
OLD: const currentLeft = parseFloat(e.target.style.left) || 0;
NEW: const currentLeft = parseFloat(e.currentTarget.style.left) || 0;
Why This Caused Intermittent Jumping:
- Click on effect body (not text) → e.target = effectDiv → works fine
- Click on effect text <small> → e.target = <small> → jumps!
- Appears random because depends on WHERE user clicks
Bug Fix #2: Left Handle Can Extend Past Sequence Start
Problem:
Math.max(0, ...) prevented negative effect start times
- Right handle could extend sequence rightward ✓
- Left handle COULDN'T extend sequence leftward ✗
- Inconsistent behavior
The Fix:
Remove Math.max(0, ...) constraint
Allow negative effect start times
OLD: effect.startTime = Math.max(0, Math.min(..., effect.endTime - 0.1));
NEW: effect.startTime = Math.min(newStartTime, effect.endTime - 0.1);
How It Works Now:
1. Drag left handle past sequence start
2. effect.startTime becomes negative (e.g., -2.0)
3. renderTimeline() calculates sequence bounds:
seqVisualStart = seq.startTime + min(effect.startTime)
= 10.0 + (-2.0) = 8.0
4. Sequence box extends leftward automatically!
Example:
Sequence at t=10s with effect [0.0, 5.0]
Drag left handle to t=8s:
- effect.startTime = 8.0 - 10.0 = -2.0 (relative)
- Sequence visual start = 10.0 + (-2.0) = 8.0 (absolute)
- Sequence box now starts at 8.0s ✓
Technical Details:
- e.currentTarget: Element that addEventListener was called on
- e.target: Deepest element that triggered the event
- Effect innerHTML has children: <handle><small><handle>
- Clicking text triggers event but e.target is <small>, not effectDiv
- This is a classic event delegation bug
Result: Both dragging and handles now work correctly!
|
|
Feature #1: Editable Sequence Names
- Added "Name" field to sequence property panel
- User can set custom sequence names (replaces generic "Sequence N")
- Name stored in seq.name property
- Persists in demo.seq file when saved
- Displays in large centered overlay on timeline
- Empty name falls back to "Sequence N" display
Property Panel:
[Name ] ← NEW: editable text field
[Start Time ]
[Priority ]
[Apply]
Usage: Select sequence → Edit name in property panel → Apply
Feature #2: Effect Resize Handles
- Added draggable handles at left/right edges of selected effects
- Left handle: Adjusts start time (end time fixed)
- Right handle: Adjusts end time (start time fixed)
- Handles only visible on selected effects
- Smooth dragging with snap-to-beat support
Visual Design:
- 6px wide teal handles (rgba(78, 201, 176, 0.8))
- Cursor: ew-resize (horizontal resize)
- Hover: Expands to 8px, full opacity
- z-index: 10 (above effect content)
- Border radius matches effect corners
Handle Dragging Algorithm:
1. Click handle → startHandleDrag(type: 'left'|'right')
2. mousemove → onHandleDrag:
- Calculate newTime from mouse position
- Apply snap-to-beat if enabled
- Convert to sequence-relative time
- If left handle: effect.startTime = min(newTime, endTime - 0.1)
- If right handle: effect.endTime = max(startTime + 0.1, newTime)
3. mouseup → stopHandleDrag
4. renderTimeline() → recalculates sequence bounds
Technical Details:
- Global state: isDraggingHandle, handleType
- Separate drag handlers from effect move
- Minimum effect duration: 0.1 seconds
- Prevents handle overlap (start < end enforced)
- Works with beat snapping when enabled
- Property panel updates in real-time
CSS:
.effect-handle {
position: absolute;
width: 6px;
height: 100%;
cursor: ew-resize;
display: none (only on .effect.selected)
}
Event Flow:
Click handle → stopPropagation (don't trigger effect drag)
↓
startHandleDrag → set isDraggingHandle, handleType
↓
mousemove → onHandleDrag → adjust start/end time
↓
mouseup → stopHandleDrag → cleanup
↓
renderTimeline → sequence bounds recalculate
↓
updateProperties → panel shows new times
User Experience:
- Select effect → handles appear at edges
- Drag left handle → shorten/lengthen from start
- Drag right handle → shorten/lengthen from end
- Visual feedback: effect resizes in real-time
- Sequence box adjusts to fit resized effect
- Property panel shows updated times immediately
|
|
Bug Fix #1: Effect Drag Offset Calculation
- Fixed erratic jumping when clicking/dragging effects
- Problem: dragOffset calculated from element edge, not timeline origin
- Old calculation:
dragOffset.x = e.clientX - rect.left (element-relative)
- New calculation:
dragOffset.x = e.clientX - timelineRect.left - currentLeft (timeline-relative)
- Now correctly accounts for element's current position on timeline
- Dragging feels natural, no unexpected jumps
Bug Fix #2: Effect Positioning Relative to Sequence
- Effects now correctly positioned relative to parent sequence
- Problem: Effects were using absolute timeline positions
- Old behavior: effect.startTime = newTime (absolute)
- New behavior: effect.startTime = newTime - seq.startTime (relative)
- Algorithm:
1. Calculate newTime from mouse position (absolute timeline)
2. Convert to relative: relativeTime = newTime - seq.startTime
3. Store relative time in effect
4. Rendering uses: seq.startTime + effect.startTime (absolute)
- Sequence bounds now update correctly after effect moves
Bug Fix #3: Property Panel Updates Trigger Re-render
- Property changes now properly update timeline visual
- Added updateProperties() call after renderTimeline()
- Ensures property panel shows calculated values
- Cascade of events after property change:
a) Update data model (sequence/effect properties)
b) renderTimeline() → recalculates sequence bounds
c) updateProperties() → refreshes property panel display
d) showMessage() → user feedback
- Sequence start/end bounds recalculate correctly
- Visual updates immediately reflect property changes
Technical Details:
- startDrag: dragOffset from timeline origin, not element
- onDrag: Convert absolute position to sequence-relative time
- applyProperties: Call both renderTimeline() and updateProperties()
- Sequence visual bounds: calculated dynamically during render
* seqVisualStart = seq.startTime + min(effect.startTime)
* seqVisualEnd = seq.startTime + max(effect.endTime)
Result: All three operations (drag, property edit, bounds calc) work correctly
|
|
Feature #1: Re-order Sequences by Time
- Added "🔄 Re-order by Time" button to controls
- Sorts sequences by startTime (ascending order)
- Preserves focus on currently active sequence
- Algorithm:
1. Store reference to current active sequence (lastActiveSeqIndex)
2. Sort sequences array: sequences.sort((a, b) => a.startTime - b.startTime)
3. Re-render timeline (recalculates _yPosition for all)
4. Find new index of previously active sequence
5. Scroll to its new Y position
6. Update lastActiveSeqIndex to new index
- Button enabled when file is loaded
- Shows success message after re-ordering
- Useful when sequences are added/moved out of order
Use Case:
Before: Seq2(10s), Seq0(0s), Seq1(5s) ← Out of order
After: Seq0(0s), Seq1(5s), Seq2(10s) ← Chronological order
Feature #2: 10% Viewport Slack for Visual Comfort
- Added headroom when calculating current time during scroll
- Previously: currentTime = scrollLeft / pixelsPerSecond
- Now: currentTime = (scrollLeft / pixelsPerSecond) + slack
- Slack = 10% of viewport width in time units
Benefits:
- Sequences don't get targeted when right at left edge
- More comfortable visual positioning
- Sequences become active when ~10% into viewport
- Prevents "edge hugging" during diagonal scroll
Example:
Viewport width: 1000px, pixelsPerSecond: 100
Slack = (1000 / 100) * 0.1 = 1.0 second
scrollLeft = 500px → currentTime = 5.0s + 1.0s = 6.0s
Sequence at 6.0s becomes active (not 5.0s)
Technical Details:
- viewportWidth = timelineContainer.clientWidth
- slack = (viewportWidth / pixelsPerSecond) * 0.1
- Applied before finding target sequence
- Works with any zoom level (pixelsPerSecond changes)
- Dynamic calculation on every wheel event
|
|
Bug Fix #1: Remove Current Time Indicator
- Removed vertical time indicator line (user feedback: didn't look good)
- Deleted .current-time-indicator CSS class
- Removed HTML element from timeline-container
- Cleaner visual appearance without the distracting line
Bug Fix #2: Dynamic Y Positioning to Prevent Overlap
- Sequences now use cumulative Y positioning instead of fixed spacing
- Previously: seqIndex * 80px (fixed spacing caused overlaps)
- Now: Accumulate Y position based on actual sequence heights
Algorithm:
1. Track cumulativeY starting at 0
2. Calculate each sequence height dynamically:
height = max(70, 20 + numEffects * 30 + 5)
3. Position sequence at cumulativeY
4. Store Y position in seq._yPosition
5. Increment: cumulativeY += height + 10px gap
6. Effects use seq._yPosition + offset
7. Scroll handler uses seq._yPosition for target
Example (3 sequences with different effect counts):
Before (overlap): After (no overlap):
Seq0: y=0, h=70 Seq0: y=0, h=70
Seq1: y=80, h=120 ✗ Seq1: y=80, h=120
Seq2: y=160 (hidden) Seq2: y=210, h=70 ✓
Technical Changes:
- Added cumulativeY tracking variable
- Added sequenceGap = 10px constant
- Sequences store _yPosition property
- Effects use seq._yPosition instead of seqIndex * 80
- Wheel scroll uses sequences[i]._yPosition
- Properly handles varying sequence heights
Result: Sequences never overlap, regardless of effect count
|
|
Visual Enhancements:
1. Current Time Indicator (Vertical Line)
- Faint vertical line shows current scroll position
- Fixed position at left: 80px with gradient fade
- Color: rgba(78, 201, 176, 0.6) (teal/cyan)
- Gradient: fades at top/bottom for smooth appearance
- pointer-events: none (doesn't block interaction)
- z-index: 100 (appears above timeline elements)
- Guides the eye during mouse wheel navigation
2. Sequence Flash Effect
- Brief highlight when active sequence changes
- 0.6s animation: bright glow → normal state
- Keyframe animation sequenceFlash:
* Start: box-shadow 20px glow, teal border
* End: normal 10px glow, blue border
- Triggers on lastActiveSeqIndex change
- Auto-removes class after 600ms
- Helps user track which sequence is now active
3. Taller Timeline View
- timeline-container: height = calc(100vh - 280px)
- min-height: 500px (prevents over-shrinking)
- Uses full vertical real estate
- Much less squished appearance
- Better utilization of screen space
- Accommodates more sequences in viewport
Technical Implementation:
- Added lastActiveSeqIndex global state variable
- Wheel handler detects sequence index changes
- querySelector to find sequence div and add flash class
- setTimeout removes flash class after animation
- Fixed positioning for time indicator
- Responsive height calculation for container
User Experience:
- Visual feedback during diagonal scrolling
- Clear indication of current time position
- Smooth flash draws attention to sequence changes
- More comfortable editing with taller view
- Better spatial awareness of timeline position
|
|
Enhancement: Smart Vertical Scrolling
- Mouse wheel now scrolls diagonally (horizontal + vertical)
- Automatically brings relevant sequence to top-left of viewport
- Follows the time-ordered cascade of sequences
Algorithm:
1. Scroll horizontally as before (timeline.scrollLeft += deltaY)
2. Calculate current time position (left edge of viewport)
currentTime = scrollLeft / pixelsPerSecond
3. Find closest sequence at that time:
- Last sequence that starts before or at currentTime
- Sequences sorted by startTime
4. Smooth scroll vertically to target sequence:
- targetScrollTop = seqIndex * 80px
- Smooth transition: scrollTop += diff * 0.3 (not instant jump)
User Experience:
- Scroll forward in time → later sequences move to top
- Scroll backward in time → earlier sequences move to top
- Creates natural "diagonal" navigation along timeline
- Top-left corner always shows the most relevant sequence
Example timeline:
Seq 0 (0s) ──────────────
Seq 1 (5s) ──────────────
Seq 2 (10s) ──────────────
Scroll to 7s → Seq 1 moves to top (it's active at that time)
Scroll to 12s → Seq 2 moves to top (it's active at that time)
This provides intuitive navigation through time-ordered sequences.
|
|
responsive layout
Bug Fix #1: Dynamic Sequence Start Time
- Sequences now dynamically adjust start position based on earliest effect
- Sequence box shrinks from left when effects move later in time
- Calculate visual bounds: min(effect.startTime) to max(effect.endTime)
- Sequence position: seq.startTime + minEffectStart
- Sequence width: maxEffectEnd - minEffectStart
- Time display shows actual visual start time, not fixed seq.startTime
- Eliminates empty space at sequence start when effects are delayed
Bug Fix #2: Mouse Wheel Horizontal Scroll
- Mouse wheel now scrolls timeline horizontally (natural navigation)
- Prevents default vertical scroll behavior on timeline container
- More intuitive than using horizontal scrollbar
- Smooth scrolling with deltaY mapped to scrollLeft
Bug Fix #3: Responsive Layout
- Container now uses 100% width (was: fixed 1400px max)
- Added window resize event listener to re-render timeline
- Body uses box-sizing: border-box for proper padding
- Timeline recalculates on browser window resize
- Works correctly when going fullscreen
Technical details:
- seqVisualStart = seq.startTime + Math.min(effect.startTime)
- seqVisualEnd = seq.startTime + Math.max(effect.endTime)
- Wheel event uses { passive: false } to allow preventDefault()
- Window resize debouncing not needed (renderTimeline is fast)
|
|
UX improvement:
- Sequence name now displays as large centered overlay (24px bold)
- Strong text shadow for readability over effect stack
- Fades out smoothly when mouse enters sequence box (0.3s transition)
- Fades back in when mouse leaves sequence box
- Small info text (time, priority) stays in top-left corner
Visual hierarchy:
- Default: Large sequence name visible, dominates the view
- On hover: Name fades away, effects become clearly visible
- Smooth 300ms opacity transition for polished feel
CSS implementation:
- .sequence-name: Centered absolutely, z-index 10, pointer-events none
- .sequence.hovered .sequence-name: opacity 0
- .sequence-info: Small text in corner, always visible
- Multi-layer text shadow for high contrast
JavaScript:
- mouseenter: Add 'hovered' class to trigger fade out
- mouseleave: Remove 'hovered' class to restore name
- Supports custom sequence names from demo.seq file
|
|
UI improvements:
- Properties panel now floats in top-right corner (fixed position)
- Added collapse/expand button for properties panel
- Panel slides out of view when collapsed, button appears to restore
- Effects now show only class name, full details on hover (tooltip)
- Tooltip shows: ClassName, Time, Priority, Args
- Effect bars reduced from 35px to 26px height (cleaner appearance)
- Effect spacing reduced from 40px to 30px (more compact stacking)
- Effects use flexbox centering for better text alignment
- Added hover highlight for better visual feedback
CSS changes:
- Properties panel: position fixed, z-index 1000, slide animation
- Collapse button appears at top-right when panel hidden
- Effects: single-line display with ellipsis overflow
- Improved padding and font sizing for compact effect bars
The properties panel is now always accessible without scrolling to the
bottom of the page, and effect bars are much cleaner while still showing
all information on hover.
|
|
Bugs fixed:
- Effects within sequences now stack vertically instead of overlapping
- Sequence height now dynamically adjusts based on effect count
- Effects positioned with proper 40px vertical spacing
Features added:
- Seconds/Beats toggle checkbox with BPM display
- Time markers show beats (0b, 1b, etc.) when in beat mode
- Snap-to-beat when dragging in beat mode
- Effect/sequence time labels show beats when enabled
- BPM tracking from loaded demo.seq file
The effect stacking bug was caused by all effects using the same vertical
position formula (seqIndex * 80 + 25). Fixed by adding effectIndex * 40
to stack effects properly. Sequences now grow in height to accommodate
multiple stacked effects.
|
|
Documentation improvements:
1. Added reference to doc/SEQUENCE.md in README
2. Added comment in parser pointing to format spec
3. Updated README with complete format examples including:
- Priority modifiers (+, =, -)
- Time notation (beats vs seconds)
- Optional sequence names
- BPM declaration
New feature task (Phase 1):
Task 1.2b: Priority Editing UI (HIGH PRIORITY, 6-8h)
- Edit sequence priority (0-9 for scene, 10+ for post-processing)
- Toggle effect priority modifiers (+/=/-)
- Visual priority indicators and z-order visualization
- Computed priority display
- Priority conflict warnings
Implementation details:
- Radio buttons for priority modifiers
- Up/down buttons for sequence priority
- Color-coded priority levels
- Priority badges on timeline items
- Automatic priority recalculation
Rationale:
Priority control is essential for proper render order and z-stacking.
Currently, priorities are shown but not easily editable. This task
makes priority a first-class editable property.
Updated effort estimates:
- Phase 1: 28-36 hours (was 22-28)
- Total: ~117-161 hours for full feature set
|
|
Fixed critical parsing bugs that prevented loading real demo.seq files.
Issues fixed:
1. Beat notation support: Parse '0b', '4b' as beats and convert to seconds
- Added BPM parsing from '# BPM 120' comments
- Helper function: parseTime() converts beats to seconds using BPM
2. Priority modifiers: Handle '+', '=', '-' modifiers correctly
- '+' increments priority
- '=' keeps same priority
- '-' decrements priority (for background effects)
- Store both absolute priority and modifier for round-trip
3. Inline comments: Strip comments from end of lines with '#'
- Effect lines like 'EFFECT + FlashEffect 0.0 1.0 # comment' now parse
4. Sequence names: Parse optional sequence names in quotes
- Format: SEQUENCE <time> <priority> "name" [end]
5. Updated serializer: Output correct format with modifiers
- Generate 'EFFECT + ClassName ...' instead of 'EFFECT ClassName ... priority'
- Preserve BPM comment in output
- Preserve sequence names
Parser now correctly handles:
- SEQUENCE 0b 0 → Start at beat 0, priority 0
- SEQUENCE 4b 0 → Start at beat 4 (2 seconds @ 120 BPM)
- EFFECT - FlashCubeEffect .2 3 → Background effect (priority -1)
- EFFECT + FlashEffect 0.0 1. → Normal effect (priority 0)
- EFFECT = GaussianBlur 0 8 → Same priority as previous
Testing: Load assets/demo.seq should now work correctly.
|
|
Created detailed roadmap for timeline editor future development.
Phase 1: Core Editing Features (HIGH PRIORITY)
- Snap-to-beat: Musical timing with BPM-based grid (4-6h)
- Create new effects: Modal dialog for adding effects (6-8h)
- Overlap detection: Visual warnings for conflicts (8-10h)
Total: 22-28 hours
Phase 2: Productivity Enhancements (MEDIUM PRIORITY)
- Undo/redo system with command pattern (10-12h)
- Multi-select & batch operations (12-15h)
- Copy/paste & duplication (6-8h)
- Keyboard shortcuts & navigation (4-6h)
Total: 38-51 hours
Phase 3: Advanced Features (LOW PRIORITY)
- Timeline playback indicator (4-6h)
- Templates & presets (8-10h)
- Search & filter (6-8h)
- Timeline comparison view (15-20h)
- Export formats (JSON, CSV, MD) (6-8h)
- Auto-save & local storage (4-6h)
Total: 51-74 hours
Implementation Details:
- Technical approach for each feature
- UI mockups and code snippets
- Effort estimates and dependencies
- Success metrics and design principles
Priority recommendation:
1. Snap-to-beat (makes musical timing easy)
2. Create effects (essential for productivity)
3. Overlap detection (prevents rendering bugs)
Total effort for full feature set: ~110-150 hours
The roadmap provides clear guidance for incremental development
while keeping the tool simple and self-contained.
|
|
Created a functional web-based timeline editor for demo.seq files.
Features implemented:
✅ Load/save demo.seq files via browser file API
✅ Visual Gantt-style timeline with time markers
✅ Drag & drop sequences and effects along timeline
✅ Properties panel for editing timing, priorities, arguments
✅ Zoom controls (10% - 200%)
✅ Add/delete sequences and effects
✅ Real-time statistics (sequence count, effect count, duration)
✅ Dark theme matching VSCode aesthetic
✅ Color-coded items (sequences blue, effects gray)
✅ Selection highlighting
Technical details:
- Pure HTML/CSS/JavaScript (no dependencies, no build step)
- ~600 lines in single self-contained HTML file
- Works offline, no backend needed
- Parser converts demo.seq text → JavaScript objects
- Serializer converts JavaScript objects → demo.seq text
Usage:
1. Open tools/timeline_editor/index.html in browser
2. Load assets/demo.seq
3. Drag items, edit properties
4. Save modified file
5. Copy to assets/demo.seq and rebuild
Limitations (acceptable for v1):
- No undo/redo yet
- No effect creation UI (must use properties panel)
- No overlap detection warnings
- No snap-to-grid
- No preview rendering (intentional - editor only)
This provides a quick way to experiment with demo timing without
recompiling, and better visualization of sequence/effect relationships.
Size: ~25KB (HTML + embedded JS/CSS)
Status: Task #57 basic implementation complete
|
|
Generated files updated during build process after code formatting
and recent changes.
|
|
Added new low-priority task for creating a web-based interactive editor
for demo.seq files. This would evolve the existing Gantt chart HTML output
into a full interactive editor.
Features:
- Load/save demo.seq files
- Visual Gantt-style timeline
- Drag & drop sequences and effects
- Edit timing and properties
- Overlap detection
- Zoom/pan navigation
Technical scope:
- Pure HTML/JavaScript tool
- No backend or code integration
- No preview rendering
- Standalone editor for timeline files
Priority: Very Low (quality of life improvement)
Effort: 1-2 weeks for basic functionality
This addresses the need for faster iteration on demo timing without
recompiling, and better visualization of sequence overlaps.
|