From 46506cb93e768d58b17a91ec98425e6bf5691a25 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Sat, 4 Aug 2007 08:59:18 +0000 Subject: [PATCH] 2007-08-04 Emmanuele Bassi * clutter/clutter-behaviour-depth.c: Clarify that what drives the movement along the Z axis is the ClutterAlpha object (we don't have the luxury of a rollover like the opacity does); so, if you want to go from 0 to -100 you have to use a decreasing function, just as well if you want to go from 100 to 0. Using a min-depth of 100 and a max-depth of 0 and an increasing function is undefined behaviour. * tests/Makefile.am: * tests/test-depth.c: Add a test case for the depth behaviour. --- ChangeLog | 13 ++++ clutter/clutter-behaviour-depth.c | 87 +++++++++++++++--------- clutter/clutter-behaviour-depth.h | 4 +- doc/reference/clutter-sections.txt | 3 +- tests/Makefile.am | 3 +- tests/test-depth.c | 105 +++++++++++++++++++++++++++++ 6 files changed, 179 insertions(+), 36 deletions(-) create mode 100644 tests/test-depth.c diff --git a/ChangeLog b/ChangeLog index 5fea9b6a6..d0a112428 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-08-04 Emmanuele Bassi + + * clutter/clutter-behaviour-depth.c: Clarify that what drives + the movement along the Z axis is the ClutterAlpha object (we + don't have the luxury of a rollover like the opacity does); + so, if you want to go from 0 to -100 you have to use a + decreasing function, just as well if you want to go from 100 + to 0. Using a min-depth of 100 and a max-depth of 0 and an + increasing function is undefined behaviour. + + * tests/Makefile.am: + * tests/test-depth.c: Add a test case for the depth behaviour. + 2007-08-04 Emmanuele Bassi * clutter/clutter-actor.c (clutter_actor_set_opacity): Queue diff --git a/clutter/clutter-behaviour-depth.c b/clutter/clutter-behaviour-depth.c index 4087f27f7..fe1ac72d6 100644 --- a/clutter/clutter-behaviour-depth.c +++ b/clutter/clutter-behaviour-depth.c @@ -41,6 +41,11 @@ * #ClutterBehaviourDepth is a simple #ClutterBehaviour controlling the * depth of a set of actors. * + * The minimum and maximum depth are controlled by the + * ClutterBehaviourDepth:min-depth and ClutterBehaviourDepth:max-depth + * properties. The direction of the motion on the depth axis is controlled + * by the #ClutterAlpha object. + * * Since: 0.4 */ @@ -50,16 +55,16 @@ G_DEFINE_TYPE (ClutterBehaviourDepth, struct _ClutterBehaviourDepthPrivate { - gint depth_start; - gint depth_end; + gint min_depth; + gint max_depth; }; enum { PROP_0, - PROP_DEPTH_START, - PROP_DEPTH_END + PROP_MIN_DEPTH, + PROP_MAX_DEPTH }; static void @@ -75,18 +80,26 @@ clutter_behaviour_depth_alpha_notify (ClutterBehaviour *behaviour, guint32 alpha_value) { ClutterBehaviourDepthPrivate *priv; - gint delta, depth; + gint depth; priv = CLUTTER_BEHAVIOUR_DEPTH (behaviour)->priv; - if (priv->depth_end > priv->depth_start) - delta = priv->depth_end - priv->depth_start; - else - delta = priv->depth_start - priv->depth_end; + if (priv->max_depth > priv->min_depth) + { + depth = alpha_value + * (priv->max_depth - priv->min_depth) + / CLUTTER_ALPHA_MAX_ALPHA; - depth = alpha_value * delta / CLUTTER_ALPHA_MAX_ALPHA; - depth += ((priv->depth_end > priv->depth_start) ? priv->depth_start - : priv->depth_end); + depth += priv->min_depth; + } + else + { + depth = alpha_value + * (priv->min_depth - priv->max_depth) + / CLUTTER_ALPHA_MAX_ALPHA; + + depth += priv->max_depth; + } CLUTTER_NOTE (BEHAVIOUR, "alpha: %d, depth: %d", alpha_value, depth); @@ -95,6 +108,15 @@ clutter_behaviour_depth_alpha_notify (ClutterBehaviour *behaviour, GINT_TO_POINTER (depth)); } +static void +clutter_behaviour_depth_applied (ClutterBehaviour *behaviour, + ClutterActor *actor) +{ + ClutterBehaviourDepth *depth = CLUTTER_BEHAVIOUR_DEPTH (behaviour); + + clutter_actor_set_depth (actor, depth->priv->min_depth); +} + static void clutter_behaviour_depth_set_property (GObject *gobject, guint prop_id, @@ -105,11 +127,11 @@ clutter_behaviour_depth_set_property (GObject *gobject, switch (prop_id) { - case PROP_DEPTH_START: - depth->priv->depth_start = g_value_get_int (value); + case PROP_MIN_DEPTH: + depth->priv->min_depth = g_value_get_int (value); break; - case PROP_DEPTH_END: - depth->priv->depth_end = g_value_get_int (value); + case PROP_MAX_DEPTH: + depth->priv->max_depth = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); @@ -127,11 +149,11 @@ clutter_behaviour_depth_get_property (GObject *gobject, switch (prop_id) { - case PROP_DEPTH_START: - g_value_set_int (value, depth->priv->depth_start); + case PROP_MIN_DEPTH: + g_value_set_int (value, depth->priv->min_depth); break; - case PROP_DEPTH_END: - g_value_set_int (value, depth->priv->depth_end); + case PROP_MAX_DEPTH: + g_value_set_int (value, depth->priv->max_depth); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); @@ -151,31 +173,32 @@ clutter_behaviour_depth_class_init (ClutterBehaviourDepthClass *klass) gobject_class->get_property = clutter_behaviour_depth_get_property; behaviour_class->alpha_notify = clutter_behaviour_depth_alpha_notify; + behaviour_class->applied = clutter_behaviour_depth_applied; /** - * ClutterBehaviourDepth:depth-start: + * ClutterBehaviourDepth:min-depth: * * Minimum depth level to apply to the actors. * * Since: 0.4 */ g_object_class_install_property (gobject_class, - PROP_DEPTH_START, - g_param_spec_int ("depth-start", + PROP_MIN_DEPTH, + g_param_spec_int ("min-depth", "Minimum Depth", "Minimum depth to apply", G_MININT, G_MAXINT, 0, CLUTTER_PARAM_READWRITE)); /** - * ClutterBehaviourDepth:depth-end: + * ClutterBehaviourDepth:max-depth: * * Maximum depth level to apply to the actors. * * Since: 0.4 */ g_object_class_install_property (gobject_class, - PROP_DEPTH_END, - g_param_spec_int ("depth-end", + PROP_MAX_DEPTH, + g_param_spec_int ("max-depth", "Maximum Depth", "Maximum depth to apply", G_MININT, G_MAXINT, 0, @@ -193,8 +216,8 @@ clutter_behaviour_depth_init (ClutterBehaviourDepth *depth) /** * clutter_behaviour_depth_new: * @alpha: a #ClutterAlpha or %NULL - * @depth_start: minimum depth level - * @depth_end: maximum depth level + * @min_depth: minimum depth level + * @max_depth: maximum depth level * * Creates a new #ClutterBehaviourDepth which can be used to control * the ClutterActor:depth property of a set of #ClutterActors. @@ -205,15 +228,15 @@ clutter_behaviour_depth_init (ClutterBehaviourDepth *depth) */ ClutterBehaviour * clutter_behaviour_depth_new (ClutterAlpha *alpha, - gint depth_start, - gint depth_end) + gint min_depth, + gint max_depth) { g_return_val_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha), NULL); return g_object_new (CLUTTER_TYPE_BEHAVIOUR_DEPTH, "alpha", alpha, - "depth-start", depth_start, - "depth-end", depth_end, + "min-depth", min_depth, + "max-depth", max_depth, NULL); } diff --git a/clutter/clutter-behaviour-depth.h b/clutter/clutter-behaviour-depth.h index 9ff8e2f77..b156defae 100644 --- a/clutter/clutter-behaviour-depth.h +++ b/clutter/clutter-behaviour-depth.h @@ -59,8 +59,8 @@ struct _ClutterBehaviourDepthClass GType clutter_behaviour_depth_get_type (void) G_GNUC_CONST; ClutterBehaviour *clutter_behaviour_depth_new (ClutterAlpha *alpha, - gint depth_start, - gint depth_end); + gint min_depth, + gint max_depth); G_END_DECLS diff --git a/doc/reference/clutter-sections.txt b/doc/reference/clutter-sections.txt index 56b752e23..119a7d1a9 100644 --- a/doc/reference/clutter-sections.txt +++ b/doc/reference/clutter-sections.txt @@ -726,6 +726,7 @@ CLUTTER_FIXED_TO_FLOAT CLUTTER_FIXED_TO_DOUBLE CLUTTER_FLOAT_TO_FIXED CLUTTER_FLOAT_TO_INT +CLUTTER_FLOAT_TO_UINT CLUTTER_INT_TO_FIXED CLUTTER_FIXED_INT CLUTTER_FIXED_FRACTION @@ -739,7 +740,7 @@ CLUTTER_ANGLE_FROM_DEGX CLUTTER_ANGLE_TO_DEGF CLUTTER_ANGLE_TO_DEG CLUTTER_ANGLE_TO_DEGX -CLUTTER_FLOAT_TO_UINT +CLUTTER_ANGLE_MAX_DEG clutter_cosi clutter_cosx clutter_sini diff --git a/tests/Makefile.am b/tests/Makefile.am index baba97b84..06d5e9a90 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,6 @@ noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \ test-actors test-behave test-text test-entry test-project \ - test-boxes test-perspective test-rotate + test-boxes test-perspective test-rotate test-depth INCLUDES = -I$(top_srcdir)/ LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la @@ -19,5 +19,6 @@ test_project_SOURCES = test-project.c test_boxes_SOURCES = test-boxes.c test_perspective_SOURCES = test-perspective.c test_rotate_SOURCES = test-rotate.c +test_depth_SOURCES = test-depth.c EXTRA_DIST = redhand.png diff --git a/tests/test-depth.c b/tests/test-depth.c new file mode 100644 index 000000000..310332a18 --- /dev/null +++ b/tests/test-depth.c @@ -0,0 +1,105 @@ +#include +#include + +/* this is a rather contrieved test case emulating a CLUTTER_ALPHA_RAMP + * with two half-ramps. it shows that the direction of the motion on the + * Z axis of a ClutterBehaviourDepth is controlled by the ClutterAlpha + * and not by the minimum and maximum depth. + */ + +static gboolean zoom_in = TRUE; +static ClutterBehaviour *d_behave = NULL; + +static void +timeline_completed (ClutterTimeline *timeline, + gpointer user_data) +{ + ClutterAlpha *alpha; + gint min_depth, max_depth; + + if (zoom_in) + { + alpha = clutter_alpha_new_full (timeline, + CLUTTER_ALPHA_RAMP_INC, + NULL, NULL); + min_depth = -100; + max_depth = 0; + zoom_in = FALSE; + } + else + { + alpha = clutter_alpha_new_full (timeline, + CLUTTER_ALPHA_RAMP_DEC, + NULL, NULL); + min_depth = 0; + max_depth = -100; + zoom_in = TRUE; + } + + g_object_set (G_OBJECT (d_behave), + "min-depth", min_depth, + "max-depth", max_depth, + NULL); + clutter_behaviour_set_alpha (d_behave, alpha); + + clutter_timeline_rewind (timeline); + clutter_timeline_start (timeline); +} + +int +main (int argc, char *argv[]) +{ + ClutterTimeline *timeline; + ClutterActor *stage; + ClutterActor *hand, *label; + ClutterColor stage_color = { 0xcc, 0xcc, 0xcc, 0xff }; + GdkPixbuf *pixbuf; + GError *error; + + clutter_init (&argc, &argv); + + error = NULL; + pixbuf = gdk_pixbuf_new_from_file ("redhand.png", &error); + if (error) + g_error ("Unable to load redhand.png: %s", error->message); + + stage = clutter_stage_get_default (); + clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + g_signal_connect (stage, + "button-press-event", G_CALLBACK (clutter_main_quit), + NULL); + + hand = clutter_texture_new_from_pixbuf (pixbuf); + clutter_actor_set_position (hand, 240, 140); + clutter_actor_show (hand); + + label = clutter_label_new_with_text ("Mono 26", "Clutter"); + clutter_actor_set_position (label, 100, 100); + clutter_actor_show (label); + + clutter_container_add (CLUTTER_CONTAINER (stage), hand, label, NULL); + + /* five seconds, at 50 fps */ + timeline = clutter_timeline_new (250, 50); + g_signal_connect (timeline, + "completed", G_CALLBACK (timeline_completed), + NULL); + + d_behave = clutter_behaviour_depth_new (clutter_alpha_new_full (timeline, + CLUTTER_ALPHA_RAMP_DEC, + NULL, NULL), + 0, -100); + clutter_behaviour_apply (d_behave, hand); + clutter_behaviour_apply (d_behave, label); + + clutter_actor_show (stage); + + clutter_timeline_start (timeline); + + clutter_main (); + + g_object_unref (d_behave); + g_object_unref (timeline); + + return EXIT_SUCCESS; +}