Files

122 lines
4.6 KiB
C++

#include "gc/RvbScene.hpp"
#include "gc/RvbLayout.hpp"
#include <cstdint>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string>
#include <unordered_map>
#include <vector>
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<uint8_t> bytes((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
gc::RvbScene scene;
std::string error;
if (!gc::ParseRvbScene(bytes, &scene, &error)) {
std::cerr << path << ": parse failed: " << error << '\n';
return false;
}
std::vector<gc::RvbImageDraw> 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<unsigned>(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> [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;
}