1 #include <clutter/clutter.h>
2
3 #include <math.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <glib.h>
7 #include <gmodule.h>
8
9 #include "test-utils.h"
10 #include "tests/clutter-test-utils.h"
11
12 #define NHANDS 6
13
14 typedef struct SuperOH
15 {
16 ClutterActor **hand;
17 ClutterActor *bgtex;
18 ClutterActor *real_hand;
19 ClutterActor *group;
20 ClutterActor *stage;
21
22 gint stage_width;
23 gint stage_height;
24 gfloat radius;
25
26 ClutterTimeline *timeline;
27 } SuperOH;
28
29 int
30 test_actors_main (int argc, char *argv[]);
31
32 static void
on_group_destroy(ClutterActor * actor,SuperOH * oh)33 on_group_destroy (ClutterActor *actor,
34 SuperOH *oh)
35 {
36 oh->group = NULL;
37 }
38
39 static void
on_hand_destroy(ClutterActor * actor,SuperOH * oh)40 on_hand_destroy (ClutterActor *actor,
41 SuperOH *oh)
42 {
43 int i;
44
45 for (i = 0; i < NHANDS; i++)
46 {
47 if (oh->hand[i] == actor)
48 oh->hand[i] = NULL;
49 }
50 }
51
52 static gboolean
on_button_press_event(ClutterActor * actor,ClutterEvent * event,SuperOH * oh)53 on_button_press_event (ClutterActor *actor,
54 ClutterEvent *event,
55 SuperOH *oh)
56 {
57 gfloat x, y;
58
59 clutter_event_get_coords (event, &x, &y);
60
61 g_print ("*** button press event (button:%d) at %.2f, %.2f on %s ***\n",
62 clutter_event_get_button (event),
63 x, y,
64 clutter_actor_get_name (actor));
65
66 clutter_actor_hide (actor);
67
68 return TRUE;
69 }
70
71 static gboolean
input_cb(ClutterActor * stage,ClutterEvent * event,gpointer data)72 input_cb (ClutterActor *stage,
73 ClutterEvent *event,
74 gpointer data)
75 {
76 SuperOH *oh = data;
77
78 if (event->type == CLUTTER_KEY_RELEASE)
79 {
80 g_print ("*** key press event (key:%c) ***\n",
81 clutter_event_get_key_symbol (event));
82
83 if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_q)
84 {
85 clutter_test_quit ();
86
87 return TRUE;
88 }
89 else if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_r)
90 {
91 gint i;
92
93 for (i = 0; i < NHANDS; i++)
94 {
95 if (oh->hand[i] != NULL)
96 clutter_actor_show (oh->hand[i]);
97 }
98
99 return TRUE;
100 }
101 }
102
103 return FALSE;
104 }
105
106 /* Timeline handler */
107 static void
frame_cb(ClutterTimeline * timeline,gint msecs,gpointer data)108 frame_cb (ClutterTimeline *timeline,
109 gint msecs,
110 gpointer data)
111 {
112 SuperOH *oh = data;
113 gint i;
114 float rotation = clutter_timeline_get_progress (timeline) * 360.0f;
115
116 /* Rotate everything clockwise about stage center*/
117 if (oh->group != NULL)
118 clutter_actor_set_rotation_angle (oh->group, CLUTTER_Z_AXIS, rotation);
119
120 for (i = 0; i < NHANDS; i++)
121 {
122 /* Rotate each hand around there centers - to get this we need
123 * to take into account any scaling.
124 */
125 if (oh->hand[i] != NULL)
126 clutter_actor_set_rotation_angle (oh->hand[i],
127 CLUTTER_Z_AXIS,
128 -6.0 * rotation);
129 }
130 }
131
132 static void
stop_and_quit(ClutterActor * stage,SuperOH * data)133 stop_and_quit (ClutterActor *stage,
134 SuperOH *data)
135 {
136 clutter_timeline_stop (data->timeline);
137
138 clutter_test_quit ();
139 }
140
141 G_MODULE_EXPORT int
test_actors_main(int argc,char * argv[])142 test_actors_main (int argc, char *argv[])
143 {
144 SuperOH *oh;
145 gint i;
146 GError *error;
147 ClutterActor *real_hand;
148 gchar *file;
149
150 error = NULL;
151
152 clutter_test_init (&argc, &argv);
153
154 oh = g_new (SuperOH, 1);
155
156 oh->stage = clutter_test_get_stage ();
157 clutter_actor_set_size (oh->stage, 800, 600);
158 clutter_actor_set_name (oh->stage, "Default Stage");
159 clutter_actor_set_background_color (oh->stage, CLUTTER_COLOR_LightSkyBlue);
160 g_signal_connect (oh->stage, "destroy", G_CALLBACK (stop_and_quit), oh);
161
162 clutter_stage_set_title (CLUTTER_STAGE (oh->stage), "Actors");
163
164 /* Create a timeline to manage animation */
165 oh->timeline = clutter_timeline_new_for_actor (oh->stage, 6000);
166 clutter_timeline_set_repeat_count (oh->timeline, -1);
167
168 /* fire a callback for frame change */
169 g_signal_connect (oh->timeline, "new-frame", G_CALLBACK (frame_cb), oh);
170
171 file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
172 real_hand = clutter_test_utils_create_texture_from_file (file, &error);
173 if (real_hand == NULL)
174 g_error ("image load failed: %s", error->message);
175
176 g_free (file);
177
178 /* create a new actor to hold other actors */
179 oh->group = clutter_actor_new ();
180 clutter_actor_set_pivot_point (oh->group, 0.5, 0.5);
181 clutter_actor_set_layout_manager (oh->group, clutter_fixed_layout_new ());
182 clutter_actor_set_name (oh->group, "Group");
183 g_signal_connect (oh->group, "destroy", G_CALLBACK (on_group_destroy), oh);
184 clutter_actor_add_constraint (oh->group, clutter_align_constraint_new (oh->stage, CLUTTER_ALIGN_BOTH, 0.5));
185 clutter_actor_add_constraint (oh->group, clutter_bind_constraint_new (oh->stage, CLUTTER_BIND_SIZE, 0.0f));
186
187 oh->hand = g_new (ClutterActor *, NHANDS);
188
189 oh->stage_width = clutter_actor_get_width (oh->stage);
190 oh->stage_height = clutter_actor_get_height (oh->stage);
191 oh->radius = (oh->stage_width + oh->stage_height) / NHANDS;
192
193 for (i = 0; i < NHANDS; i++)
194 {
195 gint x, y, w, h;
196
197 if (i == 0)
198 {
199 oh->hand[i] = real_hand;
200 clutter_actor_set_name (oh->hand[i], "Real Hand");
201 }
202 else
203 {
204 oh->hand[i] = clutter_clone_new (real_hand);
205 clutter_actor_set_name (oh->hand[i], "Clone Hand");
206 }
207
208 clutter_actor_set_reactive (oh->hand[i], TRUE);
209
210 clutter_actor_set_size (oh->hand[i], 200, 213);
211
212 /* Place around a circle */
213 w = clutter_actor_get_width (oh->hand[i]);
214 h = clutter_actor_get_height (oh->hand[i]);
215
216 x = oh->stage_width / 2
217 + oh->radius
218 * cos (i * G_PI / (NHANDS / 2))
219 - w / 2;
220
221 y = oh->stage_height / 2
222 + oh->radius
223 * sin (i * G_PI / (NHANDS / 2))
224 - h / 2;
225
226 clutter_actor_set_position (oh->hand[i], x, y);
227 clutter_actor_set_translation (oh->hand[i], -100.f, -106.5, 0);
228
229 /* Add to our group group */
230 clutter_container_add_actor (CLUTTER_CONTAINER (oh->group), oh->hand[i]);
231
232 g_signal_connect (oh->hand[i], "button-press-event",
233 G_CALLBACK (on_button_press_event),
234 oh);
235
236 g_signal_connect (oh->hand[i], "destroy",
237 G_CALLBACK (on_hand_destroy),
238 oh);
239 }
240
241 /* Add the group to the stage */
242 clutter_container_add_actor (CLUTTER_CONTAINER (oh->stage), oh->group);
243
244 /* Show everying */
245 clutter_actor_show (oh->stage);
246
247 g_signal_connect (oh->stage, "key-release-event",
248 G_CALLBACK (input_cb),
249 oh);
250
251 /* and start it */
252 clutter_timeline_start (oh->timeline);
253
254 clutter_test_main ();
255
256 clutter_timeline_stop (oh->timeline);
257
258 /* clean up */
259 g_object_unref (oh->timeline);
260 g_free (oh->hand);
261 g_free (oh);
262
263 return EXIT_SUCCESS;
264 }
265