1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #include <Elementary.h>
6 #include <EPhysics.h>
7 #include <Evas.h>
8 
9 #define WIDTH (512)
10 #define HEIGHT (384)
11 #define DEPTH (100)
12 #define FLOOR_Y (HEIGHT - 80)
13 #define SH_THRESHOLD (250)
14 #define SH_OFFSET_X (- 16)
15 #define OFFSET_X (90)
16 #define PADDING_X_1 (16)
17 #define PADDING_X_2 (12)
18 #define PADDING_X_3 (22)
19 #define E_THRESHOLD (WIDTH + 560)
20 #define LAYER_SHADOW (10)
21 #define LAYER_LETTER (20)
22 
23 #define CENTER(total, item)  (((total) - (item)) / 2)
24 #define LIMIT(val, op, ref) (((val) op (ref)) ? (val) : (ref));
25 #define PROP_GET(pos, min, max) (((min) + ((max) - (min)) * (pos)) / (max))
26 
27 static void
_update_box_cb(void * data __UNUSED__,EPhysics_Body * body,void * event_info)28 _update_box_cb(void *data __UNUSED__, EPhysics_Body *body, void *event_info)
29 {
30    Evas_Object *image = event_info;
31    Evas_Object *shadow = evas_object_data_get(image, "shadow");
32    Evas_Object *light = evas_object_data_get(image, "light");
33    int x, y, w, h, floor_distance, alpha = 0;
34 
35    /* modify the evas object according to the body */
36    ephysics_body_evas_object_update(body);
37    evas_object_geometry_get(image, &x, &y, &w, &h);
38 
39    floor_distance = FLOOR_Y - h;
40 
41    /* Bodies penetrates the ground slightly before bouncing. */
42    /* This is to be expected in realtime physics engines. */
43    // TODO BUG: should we move the object up by the difference????
44    //y = LIMIT(y, <=, floor_distance);
45 
46    /* We should show the shadow when we're close enough to ground */
47    if (y > SH_THRESHOLD)
48      {
49         int sh_w, sh_h;
50         double pos_x;
51 
52         evas_object_image_size_get(shadow, &sh_w, &sh_h);
53         /* shadow is darker with bigger y */
54         alpha = 255 * (y - SH_THRESHOLD) / (floor_distance - SH_THRESHOLD);
55         /* and with bigger x -- it's proportional to x / WIDTH, but varies
56          * from 100 to 255.
57          */
58         pos_x = (double) x / (WIDTH - w);
59         alpha = alpha * PROP_GET(pos_x, 100, 255);
60         /* box shadow is not resized, just moved */
61         evas_object_move(shadow, x + CENTER(w, sh_w) + SH_OFFSET_X,
62                          FLOOR_Y - sh_h + 2);
63      }
64    evas_object_color_set(shadow, alpha, alpha, alpha, alpha);
65 
66    evas_object_move(light, x, y);
67    /* it's lighter with bigger y */
68    alpha = (y <= 0) ? 0 : y * 255 / floor_distance;
69    /* and with bigger x */
70    alpha = alpha * (x - OFFSET_X + 80) / (WIDTH - OFFSET_X);
71    evas_object_color_set(light, alpha, alpha, alpha, alpha);
72 }
73 
74 static void
_update_circle_cb(void * data __UNUSED__,EPhysics_Body * body,void * event_info)75 _update_circle_cb(void *data __UNUSED__, EPhysics_Body *body, void *event_info)
76 {
77    Evas_Object *image = event_info;
78    Evas_Object *shadow = evas_object_data_get(image, "shadow");
79    Evas_Object *light = evas_object_data_get(image, "light");
80    int x, y, w, h, sh_w, sh_h, alpha = 0;
81    const Evas_Map *map;
82 
83    /* modify the evas object according to the body */
84    ephysics_body_evas_object_update(body);
85    evas_object_geometry_get(image, &x, &y, &w, &h);
86 
87    evas_object_move(light, x, y);
88    alpha = x * 255 / (WIDTH - w);
89    evas_object_color_set(light, alpha, alpha, alpha, alpha);
90 
91    /* use the same map from image to the light (rotate it) */
92    map = evas_object_map_get(image);
93    evas_object_map_set(light, map);
94    evas_object_map_enable_set(light, EINA_TRUE);
95 
96    evas_object_image_size_get(shadow, &sh_w, &sh_h);
97    evas_object_move(shadow, x + CENTER(w, sh_w) + SH_OFFSET_X,
98                     FLOOR_Y - sh_h + 2);
99    alpha = 127 + alpha / 2;
100    evas_object_color_set(shadow, alpha, alpha, alpha, alpha);
101 
102    if (x > E_THRESHOLD)
103      ephysics_body_move(body, -w - 1, y, -15);
104 }
105 
106 static void
_letter_add(Evas * evas,const char * letter,Evas_Object ** image,Evas_Object ** light,Evas_Object ** shadow)107 _letter_add(Evas *evas, const char *letter, Evas_Object **image, Evas_Object **light, Evas_Object **shadow)
108 {
109    int w, h, sh_w, sh_h;
110    char buf[1024];
111 
112    snprintf(buf, sizeof(buf), PACKAGE_DATA_DIR "/logo_shadow-%s.png", letter);
113    *shadow = evas_object_image_filled_add(evas);
114    evas_object_image_file_set(*shadow, buf, NULL);
115    evas_object_image_size_get(*shadow, &sh_w, &sh_h);
116    evas_object_resize(*shadow, sh_w, sh_h);
117    evas_object_color_set(*shadow, 0, 0, 0, 0);
118    evas_object_layer_set(*shadow, LAYER_SHADOW);
119    evas_object_show(*shadow);
120 
121    snprintf(buf, sizeof(buf), PACKAGE_DATA_DIR "/logo_letter-%s.png", letter);
122    *image = evas_object_image_filled_add(evas);
123    evas_object_image_file_set(*image, buf, NULL);
124    evas_object_image_size_get(*image, &w, &h);
125    evas_object_resize(*image, w, h);
126    evas_object_layer_set(*image, LAYER_LETTER);
127    evas_object_show(*image);
128 
129    snprintf(buf, sizeof(buf), PACKAGE_DATA_DIR "/logo_light-%s.png", letter);
130    *light = evas_object_image_filled_add(evas);
131    evas_object_image_file_set(*light, buf, NULL);
132    evas_object_resize(*light, w, h);
133    evas_object_layer_set(*light, LAYER_LETTER);
134    evas_object_show(*light);
135 
136    /* allow easy access to shadow and light from the letter image */
137    evas_object_data_set(*image, "shadow", *shadow);
138    evas_object_data_set(*image, "light", *light);
139 }
140 
141 static void
_letter_body_setup_common(EPhysics_Body * body,Evas_Object * view)142 _letter_body_setup_common(EPhysics_Body *body, Evas_Object *view)
143 {
144    ephysics_body_evas_object_set(body, view, EINA_TRUE);
145    ephysics_body_mass_set(body, 1.2);
146    ephysics_body_restitution_set(body, 0.6);
147    ephysics_body_angular_movement_enable_set(body, EINA_FALSE, EINA_FALSE,
148                                              EINA_FALSE);
149 }
150 
151 static EPhysics_Body *
_letter_body_box_add(EPhysics_World * world,Evas_Object * image)152 _letter_body_box_add(EPhysics_World *world, Evas_Object *image)
153 {
154    EPhysics_Body *body = ephysics_body_box_add(world);
155 
156    _letter_body_setup_common(body, image);
157 
158    ephysics_body_event_callback_add
159      (body, EPHYSICS_CALLBACK_BODY_UPDATE, _update_box_cb, NULL);
160 
161    return body;
162 }
163 
164 static EPhysics_Body *
_letter_body_circle_add(EPhysics_World * world,Evas_Object * image)165 _letter_body_circle_add(EPhysics_World *world, Evas_Object *image)
166 {
167    EPhysics_Body *body = ephysics_body_cylinder_add(world);
168 
169    _letter_body_setup_common(body, image);
170 
171    ephysics_body_event_callback_add
172      (body, EPHYSICS_CALLBACK_BODY_UPDATE, _update_circle_cb, NULL);
173 
174    return body;
175 }
176 
177 EAPI_MAIN int
elm_main(int argc __UNUSED__,char ** argv __UNUSED__)178 elm_main(int argc __UNUSED__, char **argv __UNUSED__)
179 {
180    Evas_Object *win, *bg, *image, *light, *shadow;
181    EPhysics_Body *ground_body, *letter_body;
182    EPhysics_World *world;
183    unsigned int i = 0;
184    int x, w, h, sh_w;
185    Evas *evas;
186 
187    struct letter_desc {
188       const char *letter;
189       int padding;
190    } falling_letters[] = {
191      {"P", PADDING_X_1},
192      {"H", PADDING_X_1},
193      {"Y", PADDING_X_3},
194      {"S1", PADDING_X_2},
195      {"I", PADDING_X_2},
196      {"C", PADDING_X_3},
197      {"S2", 0}
198    };
199 
200    if (!ephysics_init())
201      return - 1;
202 
203    elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
204 
205    win = elm_win_add(NULL, "main", ELM_WIN_SPLASH);
206    elm_win_title_set(win, "EPhysics Logo");
207    elm_win_autodel_set(win, EINA_TRUE);
208    evas_object_show(win);
209 
210    bg = elm_bg_add(win);
211    elm_bg_file_set(bg, PACKAGE_DATA_DIR "/logo_background.png", NULL);
212    elm_win_resize_object_add(win, bg);
213    evas_object_size_hint_min_set(bg, WIDTH, HEIGHT);
214    evas_object_size_hint_max_set(bg, WIDTH, HEIGHT);
215    evas_object_show(bg);
216 
217    world = ephysics_world_new();
218    ephysics_world_render_geometry_set(world, 0, 0, -50, WIDTH, HEIGHT, DEPTH);
219 
220    ground_body = ephysics_body_box_add(world);
221    ephysics_body_mass_set(ground_body, EPHYSICS_BODY_MASS_STATIC);
222    ephysics_body_geometry_set(ground_body, -100, FLOOR_Y, -15, WIDTH + 800, 10,
223                               30);
224    ephysics_body_restitution_set(ground_body, 0.65);
225    ephysics_body_friction_set(ground_body, 0.8);
226 
227    evas = evas_object_evas_get(win);
228    x = OFFSET_X;
229 
230    for (i = 0; i < EINA_C_ARRAY_LENGTH(falling_letters); i++)
231      {
232         _letter_add(evas, falling_letters[i].letter, &image, &light, &shadow);
233 
234         evas_object_image_size_get(shadow, &sh_w, NULL);
235         evas_object_image_size_get(image, &w, &h);
236 
237         /* place image and light on top, above what the viewport can show */
238         evas_object_move(image, x, -h * (i + 1) - 50);
239         evas_object_move(light, x, -h * (i + 1) - 50);
240         /* place shadow below the hit-line: FLOOR_Y, centered at image */
241         evas_object_move(shadow, x + CENTER(w, sh_w), FLOOR_Y);
242 
243         x += falling_letters[i].padding + w;
244 
245         letter_body = _letter_body_box_add(world, image);
246         ephysics_body_friction_set(letter_body, 0.4);
247      }
248 
249    /* E is a circle that comes rolling on the floor */
250    _letter_add(evas, "E", &image, &light, &shadow);
251    evas_object_color_set(shadow, 255, 255, 255, 255);
252 
253    evas_object_image_size_get(shadow, &sh_w, NULL);
254    evas_object_image_size_get(image, &w, &h);
255    /* place image and light so they are above the floor,
256     * and to the left of viewport
257     */
258    evas_object_move(image, -w - 1, FLOOR_Y - h + 1);
259    evas_object_move(light, -w - 1, FLOOR_Y - h + 1);
260    /* place the shadow below the hit-line: FLOOR_Y, centered at image */
261    evas_object_move(shadow, -w - 1 + CENTER(w, sh_w), FLOOR_Y);
262 
263    letter_body = _letter_body_circle_add(world, image);
264    ephysics_body_friction_set(letter_body, 1);
265    ephysics_body_mass_set(letter_body, 1);
266    ephysics_body_angular_movement_enable_set(letter_body, EINA_FALSE,
267                                              EINA_FALSE, EINA_TRUE);
268 
269    /* make the "E" logo get into the viewport by applying an horizontal force */
270    ephysics_body_central_impulse_apply(letter_body, 390, 0, 0);
271 
272    elm_run();
273 
274    ephysics_world_del(world);
275    ephysics_shutdown();
276    elm_shutdown();
277 
278    return 0;
279 }
280 ELM_MAIN()
281