From 26a70707ab2286e188d9ccb63084acdd5cbeebc5 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Sun, 7 Nov 2010 21:35:40 +0000 Subject: [PATCH] path-constraint: Add a ::node-reached signal Emit a signal whenever a node in the path has been reached. --- clutter/clutter-marshal.list | 1 + clutter/clutter-path-constraint.c | 43 ++++++++++++++ tests/interactive/test-path-constraint.c | 71 +++++++++++++++++++++++- 3 files changed, 114 insertions(+), 1 deletion(-) diff --git a/clutter/clutter-marshal.list b/clutter/clutter-marshal.list index 26bfd472f..e5d9d5cd9 100644 --- a/clutter/clutter-marshal.list +++ b/clutter/clutter-marshal.list @@ -15,6 +15,7 @@ VOID:OBJECT,FLOAT,FLOAT VOID:OBJECT,FLOAT,FLOAT,FLAGS VOID:OBJECT,PARAM VOID:OBJECT,POINTER +VOID:OBJECT,UINT VOID:POINTER VOID:STRING,BOOLEAN,BOOLEAN VOID:STRING,INT diff --git a/clutter/clutter-path-constraint.c b/clutter/clutter-path-constraint.c index f257c9b6c..2ccbc016b 100644 --- a/clutter/clutter-path-constraint.c +++ b/clutter/clutter-path-constraint.c @@ -43,6 +43,7 @@ #include "clutter-path-constraint.h" #include "clutter-debug.h" +#include "clutter-marshal.h" #include "clutter-private.h" #define CLUTTER_PATH_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_PATH_CONSTRAINT, ClutterPathConstraintClass)) @@ -60,6 +61,8 @@ struct _ClutterPathConstraint gfloat offset; ClutterActor *actor; + + guint current_node; }; struct _ClutterPathConstraintClass @@ -77,9 +80,17 @@ enum LAST_PROPERTY }; +enum +{ + NODE_REACHED, + + LAST_SIGNAL +}; + G_DEFINE_TYPE (ClutterPathConstraint, clutter_path_constraint, CLUTTER_TYPE_CONSTRAINT); static GParamSpec *path_properties[LAST_PROPERTY] = { NULL, }; +static guint path_signals[LAST_SIGNAL] = { 0, }; static void clutter_path_constraint_update_allocation (ClutterConstraint *constraint, @@ -100,6 +111,14 @@ clutter_path_constraint_update_allocation (ClutterConstraint *constraint, allocation->y1 = position.y; allocation->x2 = allocation->x1 + width; allocation->y2 = allocation->y1 + height; + + if (knot_id != self->current_node) + { + self->current_node = knot_id; + g_signal_emit (self, path_signals[NODE_REACHED], 0, + self->actor, + self->current_node); + } } static void @@ -222,12 +241,36 @@ clutter_path_constraint_class_init (ClutterPathConstraintClass *klass) meta_class->set_actor = clutter_path_constraint_set_actor; constraint_class->update_allocation = clutter_path_constraint_update_allocation; + + /** + * ClutterPathConstraint::node-reached: + * @constraint: the #ClutterPathConstraint that emitted the signal + * @actor: the #ClutterActor using the @constraint + * @index: the index of the node that has been reached + * + * The ::node-reached signal is emitted each time a + * #ClutterPathConstraint:offset value results in the actor + * passing a #ClutterPathNode + * + * Since: 1.6 + */ + path_signals[NODE_REACHED] = + g_signal_new (I_("node-reached"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + _clutter_marshal_VOID__OBJECT_UINT, + G_TYPE_NONE, 2, + CLUTTER_TYPE_ACTOR, + G_TYPE_UINT); } static void clutter_path_constraint_init (ClutterPathConstraint *self) { self->offset = 0.0f; + self->current_node = G_MAXUINT; } /** diff --git a/tests/interactive/test-path-constraint.c b/tests/interactive/test-path-constraint.c index 040727ed4..d84a207be 100644 --- a/tests/interactive/test-path-constraint.c +++ b/tests/interactive/test-path-constraint.c @@ -1,4 +1,5 @@ #include +#include #include #define PATH_DESCRIPTION \ @@ -29,7 +30,71 @@ on_button_press (ClutterActor *actor, return TRUE; } -int +static gchar * +node_to_string (const ClutterPathNode *node) +{ + GString *buffer = g_string_sized_new (256); + gsize len = 0, i; + + switch (node->type) + { + case CLUTTER_PATH_MOVE_TO: + g_string_append (buffer, "move-to "); + len = 1; + break; + + case CLUTTER_PATH_LINE_TO: + g_string_append (buffer, "line-to "); + len = 1; + break; + + case CLUTTER_PATH_CURVE_TO: + g_string_append (buffer, "curve-to "); + len = 3; + break; + + case CLUTTER_PATH_CLOSE: + g_string_append (buffer, "close"); + len = 0; + break; + + default: + break; + } + + for (i = 0; i < len; i++) + { + if (i == 0) + g_string_append (buffer, "[ "); + + g_string_append_printf (buffer, "[ %d, %d ]", + node->points[i].x, + node->points[i].y); + + if (i == len - 1) + g_string_append (buffer, " ]"); + } + + return g_string_free (buffer, FALSE); +} + +static void +on_node_reached (ClutterPathConstraint *constraint, + ClutterActor *actor, + guint index_) +{ + ClutterPath *path = clutter_path_constraint_get_path (constraint); + ClutterPathNode node; + gchar *str; + + clutter_path_get_node (path, index_, &node); + + str = node_to_string (&node); + g_print ("Node %d reached: %s\n", index_, str); + g_free (str); +} + +G_MODULE_EXPORT int test_path_constraint_main (int argc, char *argv[]) { @@ -54,6 +119,10 @@ test_path_constraint_main (int argc, clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); g_signal_connect (rect, "button-press-event", G_CALLBACK (on_button_press), NULL); + g_signal_connect (clutter_actor_get_constraint (rect, "path"), + "node-reached", + G_CALLBACK (on_node_reached), + NULL); clutter_actor_show (stage);