0b4899ef23
The build for interactive tests creates symbolic links for the data under tests/data; it also uses symbolic links for creating "binaries" for each interactive test. This is less than ideal, though. Instead, the tests should build a path to the data files by using a pre-processor define like TESTS_DATADIR; both g_build_filename() and pre-processor string concatenation can be used to generate a valid file name with the full path to the files. The build system should also create wrapper scripts, just like we do inside the conformance test suite, to be able to launch single tests.
267 lines
6.4 KiB
C
267 lines
6.4 KiB
C
#include <clutter/clutter.h>
|
|
|
|
#include <math.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <glib.h>
|
|
#include <gmodule.h>
|
|
|
|
#define NHANDS 6
|
|
|
|
typedef struct SuperOH
|
|
{
|
|
ClutterActor **hand, *bgtex;
|
|
ClutterActor *real_hand;
|
|
ClutterActor *group;
|
|
ClutterActor *stage;
|
|
|
|
gint stage_width;
|
|
gint stage_height;
|
|
gfloat radius;
|
|
|
|
ClutterBehaviour *scaler_1;
|
|
ClutterBehaviour *scaler_2;
|
|
ClutterTimeline *timeline;
|
|
} SuperOH;
|
|
|
|
static gint n_hands = NHANDS;
|
|
|
|
static GOptionEntry super_oh_entries[] = {
|
|
{
|
|
"num-hands", 'n',
|
|
0,
|
|
G_OPTION_ARG_INT, &n_hands,
|
|
"Number of hands", "HANDS"
|
|
},
|
|
{ NULL }
|
|
};
|
|
|
|
static gboolean
|
|
on_button_press_event (ClutterActor *actor,
|
|
ClutterEvent *event,
|
|
SuperOH *oh)
|
|
{
|
|
gfloat x, y;
|
|
|
|
clutter_event_get_coords (event, &x, &y);
|
|
|
|
g_print ("*** button press event (button:%d) at %.2f, %.2f ***\n",
|
|
clutter_event_get_button (event),
|
|
x, y);
|
|
|
|
clutter_actor_hide (actor);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
input_cb (ClutterActor *stage,
|
|
ClutterEvent *event,
|
|
gpointer data)
|
|
{
|
|
SuperOH *oh = data;
|
|
|
|
if (event->type == CLUTTER_KEY_RELEASE)
|
|
{
|
|
g_print ("*** key press event (key:%c) ***\n",
|
|
clutter_event_get_key_symbol (event));
|
|
|
|
if (clutter_event_get_key_symbol (event) == CLUTTER_q)
|
|
{
|
|
clutter_main_quit ();
|
|
|
|
return TRUE;
|
|
}
|
|
else if (clutter_event_get_key_symbol (event) == CLUTTER_r)
|
|
{
|
|
gint i;
|
|
|
|
for (i = 0; i < n_hands; i++)
|
|
clutter_actor_show (oh->hand[i]);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* Timeline handler */
|
|
static void
|
|
frame_cb (ClutterTimeline *timeline,
|
|
gint msecs,
|
|
gpointer data)
|
|
{
|
|
SuperOH *oh = data;
|
|
gint i;
|
|
float rotation = clutter_timeline_get_progress (timeline) * 360.0f;
|
|
|
|
/* Rotate everything clockwise about stage center*/
|
|
|
|
clutter_actor_set_rotation (oh->group,
|
|
CLUTTER_Z_AXIS,
|
|
rotation,
|
|
oh->stage_width / 2,
|
|
oh->stage_height / 2,
|
|
0);
|
|
|
|
for (i = 0; i < n_hands; i++)
|
|
{
|
|
/* Rotate each hand around there centers - to get this we need
|
|
* to take into account any scaling.
|
|
*/
|
|
clutter_actor_set_rotation (oh->hand[i],
|
|
CLUTTER_Z_AXIS,
|
|
-6.0 * rotation,
|
|
0, 0, 0);
|
|
}
|
|
}
|
|
|
|
static gdouble
|
|
my_sine_wave (ClutterAlpha *alpha,
|
|
gpointer dummy G_GNUC_UNUSED)
|
|
{
|
|
ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
|
|
gdouble progress = clutter_timeline_get_progress (timeline);
|
|
|
|
return sin (progress * G_PI);
|
|
}
|
|
|
|
G_MODULE_EXPORT int
|
|
test_actors_main (int argc, char *argv[])
|
|
{
|
|
ClutterAlpha *alpha;
|
|
ClutterActor *stage;
|
|
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
|
SuperOH *oh;
|
|
gint i;
|
|
GError *error;
|
|
ClutterActor *real_hand;
|
|
gchar *file;
|
|
|
|
error = NULL;
|
|
|
|
clutter_init_with_args (&argc, &argv,
|
|
NULL,
|
|
super_oh_entries,
|
|
NULL,
|
|
&error);
|
|
if (error)
|
|
{
|
|
g_warning ("Unable to initialise Clutter:\n%s",
|
|
error->message);
|
|
g_error_free (error);
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
stage = clutter_stage_get_default ();
|
|
clutter_actor_set_size (stage, 800, 600);
|
|
|
|
clutter_stage_set_title (CLUTTER_STAGE (stage), "Clone Test");
|
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
|
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
|
|
|
|
oh = g_new (SuperOH, 1);
|
|
oh->stage = stage;
|
|
|
|
/* Create a timeline to manage animation */
|
|
oh->timeline = clutter_timeline_new (6000);
|
|
clutter_timeline_set_loop (oh->timeline, TRUE);
|
|
|
|
/* fire a callback for frame change */
|
|
g_signal_connect (oh->timeline, "new-frame", G_CALLBACK (frame_cb), oh);
|
|
|
|
/* Set up some behaviours to handle scaling */
|
|
alpha = clutter_alpha_new_with_func (oh->timeline, my_sine_wave, NULL, NULL);
|
|
|
|
oh->scaler_1 = clutter_behaviour_scale_new (alpha, 0.5, 0.5, 1.0, 1.0);
|
|
oh->scaler_2 = clutter_behaviour_scale_new (alpha, 1.0, 1.0, 0.5, 0.5);
|
|
|
|
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
|
real_hand = clutter_texture_new_from_file (file, &error);
|
|
if (real_hand == NULL)
|
|
g_error ("image load failed: %s", error->message);
|
|
|
|
g_free (file);
|
|
|
|
/* create a new group to hold multiple actors in a group */
|
|
oh->group = clutter_group_new();
|
|
|
|
oh->hand = g_new (ClutterActor*, n_hands);
|
|
|
|
oh->stage_width = clutter_actor_get_width (stage);
|
|
oh->stage_height = clutter_actor_get_height (stage);
|
|
oh->radius = (oh->stage_width + oh->stage_height)
|
|
/ n_hands;
|
|
|
|
for (i = 0; i < n_hands; i++)
|
|
{
|
|
gint x, y, w, h;
|
|
|
|
if (i == 0)
|
|
oh->hand[i] = real_hand;
|
|
else
|
|
oh->hand[i] = clutter_clone_new (real_hand);
|
|
|
|
clutter_actor_set_reactive (oh->hand[i], TRUE);
|
|
|
|
clutter_actor_set_size (oh->hand[i], 200, 213);
|
|
|
|
/* Place around a circle */
|
|
w = clutter_actor_get_width (oh->hand[i]);
|
|
h = clutter_actor_get_height (oh->hand[i]);
|
|
|
|
x = oh->stage_width / 2
|
|
+ oh->radius
|
|
* cos (i * G_PI / (n_hands / 2))
|
|
- w / 2;
|
|
|
|
y = oh->stage_height / 2
|
|
+ oh->radius
|
|
* sin (i * G_PI / (n_hands / 2))
|
|
- h / 2;
|
|
|
|
clutter_actor_set_position (oh->hand[i], x, y);
|
|
|
|
clutter_actor_move_anchor_point_from_gravity (oh->hand[i],
|
|
CLUTTER_GRAVITY_CENTER);
|
|
|
|
/* Add to our group group */
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (oh->group), oh->hand[i]);
|
|
|
|
g_signal_connect (oh->hand[i], "button-press-event",
|
|
G_CALLBACK (on_button_press_event),
|
|
oh);
|
|
|
|
if (i % 2)
|
|
clutter_behaviour_apply (oh->scaler_1, oh->hand[i]);
|
|
else
|
|
clutter_behaviour_apply (oh->scaler_2, oh->hand[i]);
|
|
}
|
|
|
|
/* Add the group to the stage */
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), oh->group);
|
|
|
|
/* Show everying */
|
|
clutter_actor_show (stage);
|
|
|
|
g_signal_connect (stage, "key-release-event",
|
|
G_CALLBACK (input_cb),
|
|
oh);
|
|
|
|
/* and start it */
|
|
clutter_timeline_start (oh->timeline);
|
|
|
|
clutter_main ();
|
|
|
|
/* clean up */
|
|
g_object_unref (oh->scaler_1);
|
|
g_object_unref (oh->scaler_2);
|
|
g_object_unref (oh->timeline);
|
|
g_free (oh->hand);
|
|
g_free (oh);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|