diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/seq_compiler.cc | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/tools/seq_compiler.cc b/tools/seq_compiler.cc new file mode 100644 index 0000000..8da4e4e --- /dev/null +++ b/tools/seq_compiler.cc @@ -0,0 +1,130 @@ +// 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 <fstream> +#include <iostream> +#include <sstream> +#include <string> +#include <vector> + +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::vector<EffectEntry> effects; +}; + +std::string trim(const std::string &str) { + size_t first = str.find_first_not_of(" "); + if (std::string::npos == first) + return str; + size_t last = str.find_last_not_of(" "); + return str.substr(first, (last - first + 1)); +} + +int main(int argc, char *argv[]) { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " <input.seq> <output.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<SequenceEntry> sequences; + SequenceEntry *current_seq = nullptr; + + std::string line; + int line_num = 0; + while (std::getline(in_file, line)) { + line_num++; + std::string trimmed = trim(line); + if (trimmed.empty() || trimmed[0] == '#') + continue; + + std::stringstream ss(trimmed); + std::string command; + ss >> command; + + if (command == "SEQUENCE") { + std::string start, priority; + if (!(ss >> start >> priority)) { + std::cerr << "Error line " << line_num + << ": SEQUENCE requires <start> <priority>\n"; + return 1; + } + sequences.push_back({start, priority, {}}); + current_seq = &sequences.back(); + } else if (command == "EFFECT") { + if (!current_seq) { + std::cerr << "Error line " << line_num + << ": EFFECT found outside of SEQUENCE\n"; + return 1; + } + std::string class_name, start, end, priority; + if (!(ss >> class_name >> start >> end >> priority)) { + std::cerr << "Error line " << line_num + << ": EFFECT requires <Class> <start> <end> <priority>\n"; + return 1; + } + + // Capture remaining args + std::string extra_args; + std::getline(ss, extra_args); // Read rest of line + // Remove leading whitespace from getline if any (getline reads the space after priority) + extra_args = trim(extra_args); + if (!extra_args.empty()) { + extra_args = ", " + extra_args; + } + + current_seq->effects.push_back( + {class_name, start, end, priority, extra_args}); + } else { + std::cerr << "Error line " << line_num << ": Unknown command '" << command + << "'\n"; + return 1; + } + } + + std::ofstream out_file(argv[2]); + if (!out_file.is_open()) { + std::cerr << "Error: Could not open output file " << argv[2] << "\n"; + return 1; + } + + out_file << "// Auto-generated by seq_compiler. Do not edit.\n"; + out_file << "#include \"gpu/demo_effects.h\"\n"; + out_file << "#include \"gpu/effect.h\"\n\n"; + out_file << "void LoadTimeline(MainSequence& main_seq, WGPUDevice device, " + "WGPUQueue queue, WGPUTextureFormat format) {\n"; + + for (const auto &seq : sequences) { + out_file << " {\n"; + out_file << " auto seq = std::make_shared<Sequence>();\n"; + for (const auto &eff : seq.effects) { + out_file << " seq->add_effect(std::make_shared<" << eff.class_name + << ">(device, queue, format" << eff.extra_args << "), " + << eff.start << "f, " << eff.end << "f, " << eff.priority << ");\n"; + } + out_file << " main_seq.add_sequence(seq, " << seq.start_time << "f, " + << seq.priority << ");\n"; + out_file << " }\n"; + } + + out_file << "}\n"; + + std::cout << "Successfully generated timeline with " << sequences.size() << " sequences.\n"; + + return 0; +} |
