// This file is part of the 64k demo project. // It implements the sequence compiler tool. // Converts a text-based timeline description into C++ code. #include #include #include #include #include #include struct EffectEntry { std::string class_name; std::string start; std::string end; std::string priority; std::string extra_args; }; struct SequenceEntry { std::string start_time; std::string priority; std::string end_time; // Optional: -1.0f means "no explicit end" std::vector effects; }; std::string trim(const std::string& str) { size_t first = str.find_first_not_of(" \t"); if (std::string::npos == first) return ""; // String is all whitespace, return empty string size_t last = str.find_last_not_of(" \t"); return str.substr(first, (last - first + 1)); } // Convert beat notation to time in seconds // Supports: "64b" or "64" (beats), "32.0s" or "32.0" with decimal point (seconds) std::string convert_to_time(const std::string& value, float bpm) { std::string val = value; bool is_beat = false; // Check for explicit 'b' suffix (beat) if (!val.empty() && val.back() == 'b') { is_beat = true; val.pop_back(); } // Check for explicit 's' suffix (seconds) else if (!val.empty() && val.back() == 's') { val.pop_back(); return val; // Already in seconds } // If no suffix and no decimal point, assume beats else if (val.find('.') == std::string::npos) { is_beat = true; } if (is_beat) { float beat = std::stof(val); float time = beat * 60.0f / bpm; return std::to_string(time); } return val; // Return as-is (seconds) } int main(int argc, char* argv[]) { if (argc != 3) { std::cerr << "Usage: " << argv[0] << " \n"; std::cerr << "Example: " << argv[0] << " assets/demo.seq src/generated/timeline.cc\n"; return 1; } std::ifstream in_file(argv[1]); if (!in_file.is_open()) { std::cerr << "Error: Could not open input file " << argv[1] << "\n"; return 1; } std::vector sequences; SequenceEntry* current_seq = nullptr; float bpm = 120.0f; // Default BPM std::string demo_end_time = ""; // Demo end time (optional) std::string line; int line_num = 0; while (std::getline(in_file, line)) { ++line_num; std::string trimmed = trim(line); if (trimmed.empty()) continue; // Parse BPM from comment if (trimmed[0] == '#') { std::stringstream ss(trimmed); std::string hash, keyword; ss >> hash >> keyword; if (keyword == "BPM") { ss >> bpm; std::cout << "Using BPM: " << bpm << "\n"; } continue; } std::stringstream ss(trimmed); std::string command; ss >> command; if (command == "END_DEMO") { std::string end_time; if (!(ss >> end_time)) { std::cerr << "Error line " << line_num << ": END_DEMO requires