# Workspace System (Task #77) [COMPLETED] ## Status **Implemented:** Feb 9, 2026 Workspace system is now active. Use `cmake -B build -DDEMO_WORKSPACE=` to select workspace. ## Overview Self-contained demo workspaces for parallel development and clean content separation. **Motivation:** Current structure scatters demo content across multiple locations: - `assets/demo.seq` - Timeline - `assets/music.track` - Audio - `assets/final/demo_assets.txt` - Asset list - `assets/final/music/*.spec` - Audio samples - `assets/shaders/*.wgsl` - Shaders (some demo-specific, some shared) This makes it hard to: - Work on multiple demos simultaneously - Understand what files belong to which demo - Share common resources cleanly - Onboard new developers ## Problem Statement **Current structure (flat):** ``` /assets/ demo.seq # Main demo timeline music.track # Main demo music test_demo.seq # Test demo timeline test_demo.track # Test demo music /final/ demo_assets.txt # Main demo assets /music/*.spec # Audio samples (mixed usage) /shaders/ *.wgsl # Mixed: common + demo-specific ``` **Issues:** 1. No clear ownership of files 2. Can't easily switch between demos 3. Assets intermingled (demo vs test) 4. Shaders hard to categorize (shared vs demo-specific) 5. Adding new demos requires scattered changes ## Proposed Structure ### Workspace Directory Layout ``` /workspaces/ /main/ # Main production demo workspace.cfg # Workspace metadata timeline.seq # Visual effects music.track # Audio patterns assets.txt # Asset list /assets/ /music/*.spec # Demo-specific audio /meshes/*.obj # Demo-specific meshes /shaders/ # Demo-specific shaders custom_effect.wgsl /test/ # Test/validation demo workspace.cfg timeline.seq music.track assets.txt /assets/ /shaders/ /experiments/ # Experimental demos /demo2024_revision/ workspace.cfg ... /assets/common/ # Shared resources /shaders/ /math/ # Shared math utilities common_utils.wgsl sdf.wgsl /common_uniforms/ # Shared uniforms common.wgsl /audio/ standard_drums.spec # Shared samples ``` ### Workspace Configuration **`workspace.cfg` format:** ```ini [workspace] name = "Main Demo" description = "Production 64k demo" version = "1.0" [build] # Output binary name target = "demo64k" # Include paths (relative to workspace root) timeline = "timeline.seq" music = "music.track" assets = "assets.txt" # Asset directories asset_dirs = ["assets/", "../common/audio/"] # Shader directories (order matters: workspace-specific first) shader_dirs = ["shaders/", "../common/shaders/"] [options] # Default resolution width = 1280 height = 720 # Duration (seconds, -1 = auto-detect) duration = -1 # BPM for timeline bpm = 120 ``` ## Architecture ### Build System Integration **CMakeLists.txt changes:** ```cmake # Select active workspace (default: main) set(DEMO_WORKSPACE "main" CACHE STRING "Active workspace") # Parse workspace config set(WORKSPACE_DIR "${CMAKE_SOURCE_DIR}/workspaces/${DEMO_WORKSPACE}") set(WORKSPACE_CFG "${WORKSPACE_DIR}/workspace.cfg") # Read config and set variables parse_workspace_config(${WORKSPACE_CFG} TIMELINE_PATH MUSIC_PATH ASSETS_PATH ASSET_DIRS SHADER_DIRS TARGET_NAME ) # Generate assets from workspace add_custom_command( OUTPUT ${GEN_ASSETS_H} COMMAND asset_packer ${WORKSPACE_DIR}/${ASSETS_PATH} ... DEPENDS ${WORKSPACE_DIR}/${ASSETS_PATH} ) # Generate timeline from workspace add_custom_command( OUTPUT ${GEN_TIMELINE_CC} COMMAND seq_compiler ${WORKSPACE_DIR}/${TIMELINE_PATH} ... DEPENDS ${WORKSPACE_DIR}/${TIMELINE_PATH} ) # Add shader include paths from workspace foreach(SHADER_DIR ${SHADER_DIRS}) list(APPEND SHADER_INCLUDE_DIRS "${WORKSPACE_DIR}/${SHADER_DIR}") endforeach() ``` **Building specific workspace:** ```bash # Default (main workspace) cmake -S . -B build cmake --build build -j4 # Specific workspace cmake -S . -B build_test -DDEMO_WORKSPACE=test cmake --build build_test -j4 # Experimental workspace cmake -S . -B build_exp -DDEMO_WORKSPACE=experiments/demo2024_revision cmake --build build_exp -j4 ``` ### Asset Packer Changes **Support workspace-relative paths:** ```cpp // asset_packer.cc void PackerContext::resolve_asset_path(const char* rel_path) { // Try workspace-local first std::string workspace_path = workspace_dir + "/" + rel_path; if (file_exists(workspace_path)) { return workspace_path; } // Try common assets std::string common_path = "assets/common/" + rel_path; if (file_exists(common_path)) { return common_path; } error("Asset not found: %s", rel_path); } ``` ### Shader Composer Changes **Support multiple include paths:** ```cpp // shader_composer.cc class ShaderComposer { std::vector include_paths_; void add_include_path(const char* path) { include_paths_.push_back(path); } std::string resolve_include(const char* filename) { for (const auto& base : include_paths_) { std::string full = base + "/" + filename; if (file_exists(full)) { return full; } } error("Shader include not found: %s", filename); } }; ``` **Shader includes with search paths:** ```wgsl // workspace-specific shader #include "custom_uniforms.wgsl" // From workspaces/main/shaders/ #include "math/common_utils.wgsl" // From assets/common/shaders/ ``` ### CLI Tool **`scripts/workspace.sh` - Workspace management:** ```bash #!/bin/bash # workspace.sh - Manage demo workspaces case "$1" in list) # List all workspaces ls -1 workspaces/ ;; create) # Create new workspace from template NAME=$2 mkdir -p workspaces/$NAME/{assets,shaders} cp templates/workspace.cfg workspaces/$NAME/ echo "Created workspace: $NAME" ;; build) # Build specific workspace NAME=$2 cmake -S . -B build_$NAME -DDEMO_WORKSPACE=$NAME cmake --build build_$NAME -j4 ;; info) # Show workspace details NAME=$2 cat workspaces/$NAME/workspace.cfg ;; esac ``` **Usage:** ```bash ./scripts/workspace.sh list ./scripts/workspace.sh create my_demo ./scripts/workspace.sh build main ./scripts/workspace.sh info test ``` ## Implementation Plan ### Phase 1: Create Workspace Structure **1.1 Create directory tree:** ```bash mkdir -p workspaces/{main,test}/assets mkdir -p workspaces/{main,test}/shaders mkdir -p assets/common/{shaders,audio} ``` **1.2 Move existing files:** ```bash # Main demo mv assets/demo.seq workspaces/main/timeline.seq mv assets/music.track workspaces/main/music.track mv assets/final/demo_assets.txt workspaces/main/assets.txt mv assets/final/music workspaces/main/assets/ # Test demo mv assets/test_demo.seq workspaces/test/timeline.seq mv assets/test_demo.track workspaces/test/music.track cp assets/final/demo_assets.txt workspaces/test/assets.txt # Or create minimal version # Common shaders mv assets/shaders/math assets/common/shaders/ mv assets/shaders/common_uniforms assets/common/shaders/ ``` **1.3 Create workspace configs:** ```bash # Generate workspace.cfg for main and test # See format above ``` ### Phase 2: Update Build System **2.1 Add workspace parsing:** - Create `cmake/ParseWorkspace.cmake` - Parse INI-style config - Set CMake variables **2.2 Update CMakeLists.txt:** - Add `DEMO_WORKSPACE` option - Use workspace paths for assets/timeline/music - Pass shader include paths to ShaderComposer **2.3 Update compiler tools:** - `asset_packer`: Accept workspace root dir - `seq_compiler`: Accept workspace root dir - `tracker_compiler`: Accept workspace root dir ### Phase 3: Update Code **3.1 ShaderComposer:** - Add multi-path include resolution - Search workspace shaders first, then common **3.2 Asset loading:** - Update paths to match new structure - Ensure backward compatibility during transition **3.3 Generated code:** - Verify generated assets.h/timeline.cc still work - Update include paths if needed ### Phase 4: Documentation & Tools **4.1 Update docs:** - README.md: Explain workspace structure - HOWTO.md: Document workspace build commands - CONTRIBUTING.md: Workspace best practices **4.2 Create helper scripts:** - `scripts/workspace.sh`: Workspace management CLI - `templates/workspace.cfg`: Template for new workspaces **4.3 Update CI:** - Build both main and test workspaces - Validate workspace isolation ### Phase 5: Migration & Validation **5.1 Test builds:** ```bash # Build both workspaces cmake -S . -B build_main -DDEMO_WORKSPACE=main cmake --build build_main -j4 cmake -S . -B build_test -DDEMO_WORKSPACE=test cmake --build build_test -j4 # Run tests cd build_main && ctest cd build_test && ctest ``` **5.2 Verify isolation:** - Modify workspace-specific shader → only that workspace affected - Modify common shader → both workspaces affected **5.3 Update .gitignore:** ``` /build_*/ /workspaces/*/generated/ ``` ## Benefits ### 1. Clear Ownership Each workspace is self-contained: ```bash workspaces/main/ ├── workspace.cfg # Configuration ├── timeline.seq # Timeline ├── music.track # Music ├── assets.txt # Assets ├── assets/ # Local assets └── shaders/ # Local shaders ``` ### 2. Parallel Development Multiple developers can work on different demos without conflicts: ```bash # Developer A: Main demo cd workspaces/main vim timeline.seq # Developer B: Experimental demo cd workspaces/experiments/christmas_demo vim timeline.seq ``` ### 3. Easy Switching ```bash # Build main demo cmake -B build -DDEMO_WORKSPACE=main ./build/demo64k # Build test demo cmake -B build -DDEMO_WORKSPACE=test ./build/test_demo ``` ### 4. Clean Sharing Common resources in one place: ``` assets/common/ ├── shaders/ │ ├── math/ # Shared by all │ └── common_uniforms/ └── audio/ └── standard_drums.spec ``` ### 5. Scalability Easy to add new demos: ```bash ./scripts/workspace.sh create party2025 cd workspaces/party2025 # Start developing... ``` ## Migration Path ### Backward Compatibility During transition, support both structures: ```cmake if(EXISTS "${CMAKE_SOURCE_DIR}/workspaces/${DEMO_WORKSPACE}") # New workspace structure set(USING_WORKSPACES TRUE) else() # Legacy flat structure set(USING_WORKSPACES FALSE) endif() ``` ### Gradual Migration 1. **Phase 1:** Create workspace structure alongside existing 2. **Phase 2:** Update build system to support both 3. **Phase 3:** Move files to workspaces 4. **Phase 4:** Remove legacy paths 5. **Phase 5:** Update all documentation **Timeline:** 1-2 weeks for full migration ## Trade-offs ### Pros - Clear project organization - Parallel demo development - Clean resource sharing - Better onboarding for new devs - Scales to many demos ### Cons - Initial migration effort - Build system complexity increases - More directories to navigate - Learning curve for contributors ### Alternative Approaches **1. Monorepo with subprojects:** - Separate CMake projects per demo - More isolated but harder to share code **2. Configuration files only:** - Keep flat structure, use config to select files - Less clear, harder to understand ownership **3. Git branches per demo:** - Each demo is a branch - Conflicts when merging shared code **Chosen:** Workspace system (best balance) ## Implementation Effort **Estimated time: 12-16 hours** - Phase 1: Create structure (2-3 hours) - Phase 2: Build system (4-5 hours) - Phase 3: Code updates (3-4 hours) - Phase 4: Documentation (2-3 hours) - Phase 5: Validation (1-2 hours) **Priority:** Medium (improves workflow, not blocking) ## Success Criteria 1. Both `main` and `test` workspaces build successfully 2. Switching workspaces requires only CMake flag change 3. Workspace-specific changes don't affect other workspaces 4. Common shader changes affect all workspaces 5. New workspace creation takes < 5 minutes 6. All tests pass for both workspaces 7. Documentation clear for new contributors ## Related Files **New files:** - `workspaces/main/workspace.cfg` - Main demo config - `workspaces/test/workspace.cfg` - Test demo config - `cmake/ParseWorkspace.cmake` - Config parser - `scripts/workspace.sh` - Workspace CLI tool - `templates/workspace.cfg` - New workspace template **Modified files:** - `CMakeLists.txt` - Workspace support - `tools/asset_packer.cc` - Multi-path resolution - `src/gpu/effects/shader_composer.cc` - Multi-path includes - `README.md` - Workspace documentation - `doc/HOWTO.md` - Build commands - `doc/CONTRIBUTING.md` - Workspace guidelines **Moved files:** - `assets/demo.seq` → `workspaces/main/timeline.seq` - `assets/music.track` → `workspaces/main/music.track` - `assets/final/demo_assets.txt` → `workspaces/main/assets.txt` - `assets/test_demo.*` → `workspaces/test/` - `assets/shaders/math/` → `assets/common/shaders/math/` ## Notes - This is a **structural refactor**, not a feature - No runtime behavior changes - Enables future scalability - Makes project more professional - Good foundation for demoscene releases (multiple demos per repo)