Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / viewer / viewer_gpu.cpp
1 #include <cstdio>
2 #include <cmath>
3
4 #define SK_GL
5 #include <GLFW/glfw3.h>
6
7 #include "GrBackendSurface.h"
8 #include "GrDirectContext.h"
9 #include "SkCanvas.h"
10 #include "SkColorSpace.h"
11 #include "SkSurface.h"
12 #include "SkTypes.h"
13 #include "gl/GrGLInterface.h"
14
15 #include "rive/animation/linear_animation_instance.hpp"
16 #include "rive/animation/state_machine_instance.hpp"
17 #include "rive/animation/state_machine_input_instance.hpp"
18 #include "rive/animation/state_machine_number.hpp"
19 #include "rive/animation/state_machine_bool.hpp"
20 #include "rive/animation/state_machine_trigger.hpp"
21 #include "rive/artboard.hpp"
22 #include "rive/file.hpp"
23 #include "rive/layout.hpp"
24 #include "rive/math/aabb.hpp"
25 #include "skia_factory.hpp"
26 #include "skia_renderer.hpp"
27
28 #define WIDTH 1280
29 #define HEIGHT 720
30
31 rive::SkiaFactory skiaFactory;
32
33 std::string filename;
34 std::unique_ptr<rive::File> currentFile;
35 std::unique_ptr<rive::ArtboardInstance> artboardInstance;
36 std::unique_ptr<rive::Scene> currentScene;
37
38 std::vector<std::string> animationNames;
39 std::vector<std::string> stateMachineNames;
40
41 #include <time.h>
42 double GetSecondsToday() {
43     time_t m_time;
44     time(&m_time);
45     struct tm tstruct;
46     gmtime_r(&m_time, &tstruct);
47
48     int hours = tstruct.tm_hour - 4;
49     if (hours < 0) {
50         hours += 12;
51     } else if (hours >= 12) {
52         hours -= 12;
53     }
54
55     auto secs = (double)hours * 60 * 60 +
56                 (double)tstruct.tm_min * 60 +
57                 (double)tstruct.tm_sec;
58 //    printf("%d %d %d\n", tstruct.tm_sec, tstruct.tm_min, hours);
59 //    printf("%g %g %g\n", secs, secs/60, secs/60/60);
60     return secs;
61 }
62
63 std::vector<uint8_t> fileBytes;
64
65 int animationIndex = 0;
66 int stateMachineIndex = -1;
67
68 static void loadNames(const rive::Artboard* ab) {
69     animationNames.clear();
70     stateMachineNames.clear();
71     if (ab) {
72         for (size_t i = 0; i < ab->animationCount(); ++i) {
73             animationNames.push_back(ab->animationNameAt(i));
74         }
75         for (size_t i = 0; i < ab->stateMachineCount(); ++i) {
76             stateMachineNames.push_back(ab->stateMachineNameAt(i));
77         }
78     }
79 }
80
81 static void initAnimation(int index) {
82     animationIndex = index;
83     stateMachineIndex = -1;
84     assert(fileBytes.size() != 0);
85     auto file = rive::File::import(rive::toSpan(fileBytes), &skiaFactory);
86     if (!file) {
87         fileBytes.clear();
88         fprintf(stderr, "failed to import file\n");
89         return;
90     }
91     currentScene = nullptr;
92     artboardInstance = nullptr;
93
94     currentFile = std::move(file);
95     artboardInstance = currentFile->artboardDefault();
96     artboardInstance->advance(0.0f);
97     loadNames(artboardInstance.get());
98
99     if (index >= 0 && index < artboardInstance->animationCount()) {
100         currentScene = artboardInstance->animationAt(index);
101         currentScene->inputCount();
102     }
103 }
104
105
106 rive::Mat2D gInverseViewTransform;
107 rive::Vec2D lastWorldMouse;
108 static void glfwCursorPosCallback(GLFWwindow* window, double x, double y) {
109     float xscale, yscale;
110     glfwGetWindowContentScale(window, &xscale, &yscale);
111     lastWorldMouse = gInverseViewTransform * rive::Vec2D(x * xscale, y * yscale);
112     if (currentScene) {
113         currentScene->pointerMove(lastWorldMouse);
114     }
115 }
116 static void glfwMouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
117     if (currentScene) {
118         switch (action) {
119             case GLFW_PRESS:
120                 currentScene->pointerDown(lastWorldMouse);
121                 break;
122             case GLFW_RELEASE:
123                 currentScene->pointerUp(lastWorldMouse);
124                 break;
125         }
126     }
127 }
128
129 static void glfwErrorCallback(int error, const char* description) {
130     puts(description);
131 }
132
133 static void glfwDropCallback(GLFWwindow* window, int count, const char** paths) {
134     filename = paths[0];
135     FILE* fp = fopen(filename.c_str(), "rb");
136     fseek(fp, 0, SEEK_END);
137     size_t size = ftell(fp);
138     fseek(fp, 0, SEEK_SET);
139     fileBytes.resize(size);
140     if (fread(fileBytes.data(), 1, size, fp) != size) {
141         fileBytes.clear();
142         fprintf(stderr, "failed to read all of %s\n", filename.c_str());
143         return;
144     }
145     printf("Loaded %s file succesfully.\n", filename.c_str());
146     initAnimation(0);
147 }
148
149 int main() {
150     if (!glfwInit()) {
151         fprintf(stderr, "Failed to initialize glfw.\n");
152         return 1;
153     }
154     glfwSetErrorCallback(glfwErrorCallback);
155
156     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
157     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
158     GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Rive-skia GPU Viewer", NULL, NULL);
159     if (window == nullptr) {
160         fprintf(stderr, "Failed to make window or GL.\n");
161         glfwTerminate();
162         return 1;
163     }
164
165     glfwSetDropCallback(window, glfwDropCallback);
166     glfwSetCursorPosCallback(window, glfwCursorPosCallback);
167     glfwSetMouseButtonCallback(window, glfwMouseButtonCallback);
168     glfwMakeContextCurrent(window);
169
170     // Enable VSYNC.
171     glfwSwapInterval(1);
172
173     // Setup Skia
174     GrContextOptions options;
175     sk_sp<GrDirectContext> context = GrDirectContext::MakeGL(nullptr, options);
176     GrGLFramebufferInfo framebufferInfo;
177     framebufferInfo.fFBOID = 0;
178     framebufferInfo.fFormat = GL_RGBA8;
179
180     sk_sp<SkSurface> surface;
181     SkCanvas* canvas = nullptr;
182     
183     int width = 0, height = 0;
184     int lastScreenWidth = 0, lastScreenHeight = 0;
185
186     double lastTime = glfwGetTime();
187
188     static constexpr SkAlphaType at = kPremul_SkAlphaType;
189     const SkImageInfo info = SkImageInfo::MakeN32(WIDTH, HEIGHT, at);
190
191     printf("Viewer loaded. Drag and drop .riv file to load.\n");
192
193     while (!glfwWindowShouldClose(window)) {
194         glfwGetFramebufferSize(window, &width, &height);
195
196         if (!surface || width != lastScreenWidth || height != lastScreenHeight) {
197             lastScreenWidth = width;
198             lastScreenHeight = height;
199
200             SkColorType colorType = kRGBA_8888_SkColorType;
201
202             GrBackendRenderTarget backendRenderTarget(width,
203                                                       height,
204                                                       0, // sample count
205                                                       0, // stencil bits
206                                                       framebufferInfo);
207
208             surface = SkSurface::MakeFromBackendRenderTarget(context.get(),
209                                                              backendRenderTarget,
210                                                              kBottomLeft_GrSurfaceOrigin,
211                                                              colorType,
212                                                              nullptr,
213                                                              nullptr);
214
215             if (!surface) {
216                 fprintf(stderr, "Failed to create Skia surface\n");
217                 return 1;
218             }
219
220             canvas = surface->getCanvas();
221         }
222
223         double time = glfwGetTime();
224         float elapsed = (float)(time - lastTime);
225         lastTime = time;
226
227         SkPaint paint;
228         paint.setColor(SK_ColorGRAY);
229         canvas->drawPaint(paint);
230
231         if (currentScene) {
232             if (auto num = currentScene->getNumber("isTime")) {
233                 num->value(GetSecondsToday()/60/60);
234             }
235
236             currentScene->advanceAndApply(elapsed);
237
238             rive::SkiaRenderer renderer(canvas);
239             renderer.save();
240
241             auto viewTransform = rive::computeAlignment(rive::Fit::contain,
242                                                         rive::Alignment::center,
243                                                         rive::AABB(0, 0, width, height),
244                                                         currentScene->bounds());
245             renderer.transform(viewTransform);
246             gInverseViewTransform = viewTransform.invertOrIdentity();
247
248             currentScene->draw(&renderer);
249             renderer.restore();
250         }
251         context->flush();
252
253         glfwSwapBuffers(window);
254         glfwPollEvents();
255     }
256
257     glfwDestroyWindow(window);
258     glfwTerminate();
259     exit(EXIT_SUCCESS);
260 }