1 /*  RetroArch - A frontend for libretro.
2  *  Copyright (C) 2014-2017 - Jean-André Santoni
3  *  Copyright (C) 2011-2017 - Daniel De Matteis
4  *
5  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
6  *  of the GNU General Public License as published by the Free Software Found-
7  *  ation, either version 3 of the License, or (at your option) any later version.
8  *
9  *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11  *  PURPOSE.  See the GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License along with RetroArch.
14  *  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #ifndef _GFX_ANIMATION_H
18 #define _GFX_ANIMATION_H
19 
20 #include <stdint.h>
21 #include <stdlib.h>
22 
23 #include <boolean.h>
24 #include <retro_common_api.h>
25 
26 #include "font_driver.h"
27 
28 RETRO_BEGIN_DECLS
29 
30 #define TICKER_SPACER_DEFAULT "   |   "
31 
32 #define ANIM_IS_ACTIVE(_p) ((_p)->animation_is_active || (_p)->ticker_is_active)
33 
34 #define GFX_ANIMATION_CLEAR_ACTIVE(anim) \
35 { \
36    (anim)->animation_is_active = false; \
37    (anim)->ticker_is_active    = false; \
38 }
39 
40 #define GFX_ANIMATION_SET_ACTIVE(anim) \
41 { \
42    (anim)->animation_is_active = true; \
43    (anim)->ticker_is_active    = true; \
44 }
45 
46 typedef void  (*tween_cb)  (void*);
47 
48 typedef void (*update_time_cb) (float *ticker_pixel_increment,
49       unsigned width, unsigned height);
50 
51 enum gfx_animation_easing_type
52 {
53    /* Linear */
54    EASING_LINEAR    = 0,
55    /* Quad */
56    EASING_IN_QUAD,
57    EASING_OUT_QUAD,
58    EASING_IN_OUT_QUAD,
59    EASING_OUT_IN_QUAD,
60    /* Cubic */
61    EASING_IN_CUBIC,
62    EASING_OUT_CUBIC,
63    EASING_IN_OUT_CUBIC,
64    EASING_OUT_IN_CUBIC,
65    /* Quart */
66    EASING_IN_QUART,
67    EASING_OUT_QUART,
68    EASING_IN_OUT_QUART,
69    EASING_OUT_IN_QUART,
70    /* Quint */
71    EASING_IN_QUINT,
72    EASING_OUT_QUINT,
73    EASING_IN_OUT_QUINT,
74    EASING_OUT_IN_QUINT,
75    /* Sine */
76    EASING_IN_SINE,
77    EASING_OUT_SINE,
78    EASING_IN_OUT_SINE,
79    EASING_OUT_IN_SINE,
80    /* Expo */
81    EASING_IN_EXPO,
82    EASING_OUT_EXPO,
83    EASING_IN_OUT_EXPO,
84    EASING_OUT_IN_EXPO,
85    /* Circ */
86    EASING_IN_CIRC,
87    EASING_OUT_CIRC,
88    EASING_IN_OUT_CIRC,
89    EASING_OUT_IN_CIRC,
90    /* Bounce */
91    EASING_IN_BOUNCE,
92    EASING_OUT_BOUNCE,
93    EASING_IN_OUT_BOUNCE,
94    EASING_OUT_IN_BOUNCE,
95 
96    EASING_LAST
97 };
98 
99 /* TODO:
100  * Add a reverse loop ticker for languages
101  * that read right to left */
102 enum gfx_animation_ticker_type
103 {
104    TICKER_TYPE_BOUNCE = 0,
105    TICKER_TYPE_LOOP,
106    TICKER_TYPE_LAST
107 };
108 
109 typedef struct gfx_animation_ctx_entry
110 {
111    float *subject;
112    void *userdata;
113    tween_cb cb;
114    uintptr_t tag;
115    float duration;
116    float target_value;
117    enum gfx_animation_easing_type easing_enum;
118 } gfx_animation_ctx_entry_t;
119 
120 typedef struct gfx_animation_ctx_ticker
121 {
122    uint64_t idx;
123    char *s;
124    const char *str;
125    const char *spacer;
126    size_t len;
127    enum gfx_animation_ticker_type type_enum;
128    bool selected;
129 } gfx_animation_ctx_ticker_t;
130 
131 typedef struct gfx_animation_ctx_ticker_smooth
132 {
133    uint64_t idx;
134    const char *src_str;
135    const char *spacer;
136    char *dst_str;
137    unsigned *dst_str_width; /* May be set to NULL
138                                (RGUI + XMB do not require this info) */
139    unsigned *x_offset;
140    font_data_t *font;
141    size_t dst_str_len;
142    unsigned glyph_width; /* Fallback if font == NULL */
143    unsigned field_width;
144    float font_scale;
145    enum gfx_animation_ticker_type type_enum;
146    bool selected;
147 } gfx_animation_ctx_ticker_smooth_t;
148 
149 typedef struct gfx_animation_ctx_line_ticker
150 {
151    uint64_t idx;
152    const char *str;
153    char *s;
154    size_t len;
155    size_t line_len;
156    size_t max_lines;
157    enum gfx_animation_ticker_type type_enum;
158 } gfx_animation_ctx_line_ticker_t;
159 
160 typedef struct gfx_animation_ctx_line_ticker_smooth
161 {
162    uint64_t idx;
163    font_data_t *font;
164    const char *src_str;
165    float *y_offset;
166    char *dst_str;
167    size_t dst_str_len;
168    char *top_fade_str;
169    size_t top_fade_str_len;
170    float *top_fade_y_offset;
171    float *top_fade_alpha;
172    float *bottom_fade_y_offset;
173    float *bottom_fade_alpha;
174    char *bottom_fade_str;
175    size_t bottom_fade_str_len;
176    unsigned field_width;
177    unsigned field_height;
178    float font_scale;
179    enum gfx_animation_ticker_type type_enum;
180    bool fade_enabled;
181 } gfx_animation_ctx_line_ticker_smooth_t;
182 
183 typedef float gfx_timer_t;
184 
185 typedef struct gfx_timer_ctx_entry
186 {
187    tween_cb cb;
188    void *userdata;
189    float duration;
190 } gfx_timer_ctx_entry_t;
191 
192 typedef struct gfx_delayed_animation
193 {
194    gfx_animation_ctx_entry_t entry; /* pointer alignment */
195    gfx_timer_t timer;
196 } gfx_delayed_animation_t;
197 
198 typedef float (*easing_cb) (float, float, float, float);
199 
200 struct tween
201 {
202    easing_cb   easing;
203    tween_cb    cb;
204    void        *userdata;
205    uintptr_t   tag;
206    float       duration;
207    float       running_since;
208    float       initial_value;
209    float       target_value;
210    float       *subject;
211    bool        deleted;
212 };
213 
214 struct gfx_animation
215 {
216    uint64_t ticker_idx;            /* updated every TICKER_SPEED us */
217    uint64_t ticker_slow_idx;       /* updated every TICKER_SLOW_SPEED us */
218    uint64_t ticker_pixel_idx;      /* updated every frame */
219    uint64_t ticker_pixel_line_idx; /* updated every frame */
220    retro_time_t cur_time;
221    retro_time_t old_time;
222    update_time_cb updatetime_cb;   /* ptr alignment */
223                                    /* By default, this should be a NOOP */
224    struct tween* list;
225    struct tween* pending;
226 
227    float delta_time;
228 
229    bool pending_deletes;
230    bool in_update;
231    bool animation_is_active;
232    bool ticker_is_active;
233 };
234 
235 typedef struct gfx_animation gfx_animation_t;
236 
237 void gfx_animation_timer_start(gfx_timer_t *timer,
238       gfx_timer_ctx_entry_t *timer_entry);
239 
240 bool gfx_animation_update(
241       gfx_animation_t *p_anim,
242       retro_time_t current_time,
243       bool timedate_enable,
244       float ticker_speed,
245       unsigned video_width,
246       unsigned video_height);
247 
248 bool gfx_animation_ticker(gfx_animation_ctx_ticker_t *ticker);
249 
250 bool gfx_animation_ticker_smooth(gfx_animation_ctx_ticker_smooth_t *ticker);
251 
252 bool gfx_animation_line_ticker(gfx_animation_ctx_line_ticker_t *line_ticker);
253 
254 bool gfx_animation_line_ticker_smooth(gfx_animation_ctx_line_ticker_smooth_t *line_ticker);
255 
256 bool gfx_animation_kill_by_tag(uintptr_t *tag);
257 
258 bool gfx_animation_push(gfx_animation_ctx_entry_t *entry);
259 
260 void gfx_animation_push_delayed(unsigned delay, gfx_animation_ctx_entry_t *entry);
261 
262 void gfx_animation_deinit(gfx_animation_t *p_anim);
263 
264 gfx_animation_t *anim_get_ptr(void);
265 
266 RETRO_END_DECLS
267 
268 #endif
269