blob: bcfcba6fddacb43b56ff7d20d7c616976428c32d [file] [log] [blame] [edit]
#include "rive/artboard.hpp"
#include "rive/file.hpp"
#include "rive/layout.hpp"
#include "rive/animation/linear_animation_instance.hpp"
#include "low_level/low_level_renderer.hpp"
#include <string.h>
#if __APPLE__
#define GLFW_EXPOSE_NATIVE_COCOA
#endif
#include "graphics_api.hpp"
// Make sure gl3w is included before glfw3
// #include "GL/gl3w.h"
#include "GLFW/glfw3.h"
#include "GLFW/glfw3native.h"
#include <stdio.h>
void* viewerNativeWindowHandle = nullptr;
int main(int argc, const char** argv)
{
auto graphicsApi = rive::GraphicsApi::unknown;
if (argc >= 2)
{
// Figure out if the user requested a specific Graphics API.
const char* deviceName = argv[1];
if (strcmp(deviceName, "gl") == 0 || strcmp(deviceName, "opengl") == 0)
{
graphicsApi = rive::GraphicsApi::opengl;
}
else if (strcmp(deviceName, "mtl") == 0 ||
strcmp(deviceName, "metal") == 0)
{
graphicsApi = rive::GraphicsApi::metal;
}
else if (strcmp(deviceName, "vk") == 0 ||
strcmp(deviceName, "vulkan") == 0)
{
graphicsApi = rive::GraphicsApi::vulkan;
}
else if (strcmp(deviceName, "d3d11") == 0)
{
graphicsApi = rive::GraphicsApi::d3d11;
}
else if (strcmp(deviceName, "d3d12") == 0)
{
graphicsApi = rive::GraphicsApi::d3d12;
}
}
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize glfw.\n");
return 1;
}
if (graphicsApi == rive::GraphicsApi::opengl)
{
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_SAMPLES, 16);
}
else
{
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
}
GLFWwindow* window = glfwCreateWindow(640, 480, "Rive", nullptr, nullptr);
if (!window)
{
glfwTerminate();
fprintf(stderr, "Failed to create window.\n");
return -1;
}
#ifdef __APPLE__
glfwMakeContextCurrent(window);
viewerNativeWindowHandle = static_cast<void*>(glfwGetCocoaWindow(window));
#endif
// If no specific API requested, big the default one for the platform.
rive::LowLevelRenderer* renderer =
graphicsApi == rive::GraphicsApi::unknown
? rive::GraphicsApi::makeRenderer()
: rive::GraphicsApi::makeRenderer(graphicsApi);
if (renderer == nullptr || !renderer->initialize())
{
return 1;
}
char windowTitle[128];
snprintf(windowTitle,
128,
"Rive Low Level Renderer (%s)",
rive::GraphicsApi::name(renderer->type()));
glfwSetWindowTitle(window, windowTitle);
// Load a rive file
uint8_t* fileBytes = nullptr;
unsigned int fileBytesLength = 0;
// std::string filename = "assets/polygon_party.riv";
// std::string filename = "assets/triangle.riv";
// std::string filename = "assets/juice.riv";
// std::string filename = "assets/clip.riv";
// std::string filename = "assets/clipped_circle_star_2.riv";
// std::string filename = "assets/marty.riv";
std::string filename = "assets/runner.riv";
// std::string filename = "assets/rotate_square.riv";
// std::string filename = "assets/bone_deform.riv";
// std::string filename = "assets/off_road_car.riv";
// std::string filename = "assets/simple_stroke.riv";
// std::string filename = "assets/leg_issues.riv";
// std::string filename = "assets/control.riv";
// std::string filename = "assets/stroke_caps.riv";
FILE* fp = fopen(filename.c_str(), "r");
fseek(fp, 0, SEEK_END);
fileBytesLength = ftell(fp);
fseek(fp, 0, SEEK_SET);
delete[] fileBytes;
fileBytes = new uint8_t[fileBytesLength];
if (fread(fileBytes, 1, fileBytesLength, fp) != fileBytesLength)
{
delete[] fileBytes;
fprintf(stderr, "failed to read all of %s\n", filename.c_str());
return 1;
}
auto reader = rive::BinaryReader(fileBytes, fileBytesLength);
rive::File* file = nullptr;
auto result = rive::File::import(reader, &file);
if (result != rive::ImportResult::success)
{
delete[] fileBytes;
fprintf(stderr, "failed to import file\n");
return 1;
}
rive::Artboard* artboard = file->artboard();
artboard->advance(0.0f);
rive::LinearAnimationInstance* animationInstance = nullptr;
int animationIndex = 0;
rive::LinearAnimation* animation = // nullptr;
animationIndex >= 0 && animationIndex < artboard->animationCount()
? artboard->animation(animationIndex)
: nullptr;
if (animation != nullptr)
{
animationInstance = new rive::LinearAnimationInstance(animation);
}
double lastTime = glfwGetTime();
int lastWidth = 0, lastHeight = 0;
float projection[16] = {0.0f};
while (!glfwWindowShouldClose(window))
{
int width = 0, height = 0;
glfwGetFramebufferSize(window, &width, &height);
if (lastWidth != width || lastHeight != height)
{
lastWidth = width;
lastHeight = height;
renderer->orthographicProjection(
projection, 0.0f, width, height, 0.0f, 0.0f, 1.0f);
renderer->modelViewProjection(projection);
}
double time = glfwGetTime();
float elapsed = (float)(time - lastTime);
lastTime = time;
renderer->startFrame();
if (artboard != nullptr)
{
if (animationInstance != nullptr)
{
animationInstance->advance(elapsed * 0.25f);
animationInstance->apply(artboard);
}
artboard->advance(elapsed);
renderer->save();
renderer->align(rive::Fit::contain,
rive::Alignment::center,
rive::AABB(0, 0, width, height),
artboard->bounds());
artboard->draw(renderer);
renderer->restore();
}
renderer->endFrame();
#if __APPLE__
glfwSwapBuffers(window);
#endif
glfwPollEvents();
}
glfwTerminate();
return 0;
}