#include "gc/RvbScene.hpp" #include "gc/RvbLayout.hpp" #include #include #include #include #include #include #include #include namespace { void printNode(const gc::RvbNode& node, unsigned depth) { std::cout << " " << std::string(depth * 2, ' ') << node.tag << " @0x" << std::hex << node.offset << "/0x" << node.size << std::dec << " local=" << node.localDataSize << '\n'; for (const gc::RvbNode& child : node.children) printNode(child, depth + 1); } bool probe(const std::string& path, bool tree, const std::string& symbol, const gc::RvbSnapshotState& state) { std::ifstream file(path, std::ios::binary); if (!file) { std::cerr << path << ": could not open\n"; return false; } std::vector bytes((std::istreambuf_iterator(file)), std::istreambuf_iterator()); gc::RvbScene scene; std::string error; if (!gc::ParseRvbScene(bytes, &scene, &error)) { std::cerr << path << ": parse failed: " << error << '\n'; return false; } std::vector snapshot; const bool built = symbol.empty() ? gc::BuildRvbSnapshot(bytes, scene, state, &snapshot, &error) : gc::BuildRvbSymbolSnapshot(bytes, scene, symbol, state, &snapshot, &error); if (!built) { std::cerr << path << ": snapshot failed: " << error << '\n'; return false; } const uint32_t animationFrames = symbol.empty() ? gc::MeasureRvbSnapshotAnimationFrames(bytes, scene, state, &error) : 1; std::cout << path << "\n movie=" << scene.sourceWidth << 'x' << scene.sourceHeight << " @ " << static_cast(scene.framesPerSecond) << " fps" << " bindings=" << scene.bindings.size() << " images=" << scene.images.size() << " animationFrames=" << animationFrames << " initialDraws=" << snapshot.size() << "\n chunks:"; for (const gc::RvbChunk& chunk : scene.chunks) { std::cout << ' ' << chunk.tag << "@0x" << std::hex << chunk.offset << "/0x" << chunk.size << std::dec; } std::cout << "\n PREP bindings:\n"; for (const gc::RvbBinding& binding : scene.bindings) { std::cout << " " << std::left << std::setw(28) << binding.action << ' ' << binding.instancePath << '\n'; } if (tree) { std::cout << " animation tree:\n"; for (const gc::RvbNode& root : scene.roots) printNode(root, 0); std::cout << " initial draws:\n"; for (const gc::RvbImageDraw& draw : snapshot) { std::cout << " " << draw.imageSymbol << " depth=" << draw.depth << " path=" << draw.instancePath << " rgba=(" << draw.color[0] << ',' << draw.color[1] << ',' << draw.color[2] << ',' << draw.alpha << ')' << " tl=(" << draw.corners[0][0] << ',' << draw.corners[0][1] << ") br=(" << draw.corners[3][0] << ',' << draw.corners[3][1] << ")\n"; } } return true; } } // namespace int main(int argc, char** argv) { bool tree = false; std::string symbol; gc::RvbSnapshotState state; int firstPath = 1; while (firstPath < argc) { const std::string option = argv[firstPath]; if (option == "--tree") { tree = true; ++firstPath; } else if (option == "--include-other") { state.includeRootOther = true; ++firstPath; } else if (option == "--symbol" && firstPath + 1 < argc) { symbol = argv[firstPath + 1]; firstPath += 2; } else if (option == "--state" && firstPath + 1 < argc) { const std::string value = argv[firstPath + 1]; const size_t equals = value.find('='); if (equals == std::string::npos) { std::cerr << "--state expects /path=frame_label\n"; return 2; } state.frameByPath[value.substr(0, equals)] = value.substr(equals + 1); firstPath += 2; } else { break; } } if (argc <= firstPath) { std::cerr << "Usage: " << argv[0] << " [--tree] [--include-other] [--symbol name]" " [--state /path=frame] [scene.rvb ...]\n"; return 2; } bool ok = true; for (int i = firstPath; i < argc; ++i) ok = probe(argv[i], tree, symbol, state) && ok; return ok ? 0 : 1; }