From ee9a4d02bba8bb0cf6ea73c5cdcce49fb29f786e Mon Sep 17 00:00:00 2001 From: Elliot Smith Date: Wed, 24 Nov 2010 12:22:12 +0000 Subject: [PATCH] cookbook: Add example of scaling a texture Added a simple application for scaling a texture while keeping the mouse pointer over the same coordinates on its surface. --- doc/cookbook/examples/Makefile.am | 2 + doc/cookbook/examples/animations-scaling-zoom.c | 155 ++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 doc/cookbook/examples/animations-scaling-zoom.c diff --git a/doc/cookbook/examples/Makefile.am b/doc/cookbook/examples/Makefile.am index 64b3e29..7d3ed2a 100644 --- a/doc/cookbook/examples/Makefile.am +++ b/doc/cookbook/examples/Makefile.am @@ -13,6 +13,7 @@ noinst_PROGRAMS = \ animations-reuse \ animations-rotating \ animations-scaling \ + animations-scaling-zoom \ text-shadow \ textures-reflection \ textures-split-go \ @@ -68,6 +69,7 @@ animations_moving_state_SOURCES = animations-moving-state.c animations_reuse_SOURCES = animations-reuse.c animations_rotating_SOURCES = animations-rotating.c animations_scaling_SOURCES = animations-scaling.c +animations_scaling_zoom_SOURCES = animations-scaling-zoom.c text_shadow_SOURCES = text-shadow.c textures_reflection_SOURCES = textures-reflection.c textures_split_go_SOURCES = textures-split-go.c diff --git a/doc/cookbook/examples/animations-scaling-zoom.c b/doc/cookbook/examples/animations-scaling-zoom.c new file mode 100644 index 0000000..023b567 --- /dev/null +++ b/doc/cookbook/examples/animations-scaling-zoom.c @@ -0,0 +1,155 @@ +/* + * Load an image into a texture, which can then be zoomed in/out + * (double click on button 1, double click on button 3 respectively); + * also resets the texture to the stage center when a key is pressed + * (better would be to prevent drags taking the actor off-stage, + * but the implementation is much more complicated) + */ +#include +#include + +#define STAGE_SIDE 400.0 + +static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff }; + +/* on key press, center the actor on the stage; + * useful if you drag it off-stage accidentally + */ +static gboolean +key_press_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + gfloat width, height; + + clutter_actor_get_size (actor, &width, &height); + + clutter_actor_set_anchor_point (actor, width / 2, height / 2); + + clutter_actor_set_position (actor, + STAGE_SIDE / 2, + STAGE_SIDE / 2); + + return TRUE; +} + +/* on double click, zoom in on the clicked point; + * also keeps scale in the range 0.1 to 20 + */ +static gboolean +clicked_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + gdouble scale; + gfloat click_x, click_y; + gfloat click_target_x, click_target_y; + guint32 button; + + /* don't do anything unless there was a double click */ + if (clutter_event_get_click_count (event) < 2) + return TRUE; + + /* work out new scale */ + button = clutter_event_get_button (event); + + clutter_actor_get_scale (actor, &scale, NULL); + + if (button == 1) + scale *= 1.2; + else if (button == 3) + scale /= 1.2; + + /* don't do anything if scale is outside bounds */ + if (scale < 0.1 || scale > 20.0) + return TRUE; + + /* get the location of the click on the scaled actor */ + clutter_event_get_coords (event, &click_x, &click_y); + clutter_actor_transform_stage_point (actor, + click_x, click_y, + &click_target_x, &click_target_y); + + /* anchor the actor on the clicked point on its surface */ + clutter_actor_set_anchor_point (actor, click_target_x, click_target_y); + + /* set the actor's position to the click coords: it won't move, + * because the anchor point is already there; but + * the scale will now be centered on these coords (as the + * scale center defaults to the anchor point); so the anchor point + * on the actor won't move from under the pointer + */ + clutter_actor_set_position (actor, click_x, click_y); + + clutter_actor_animate (actor, CLUTTER_LINEAR, 500, + "scale-x", scale, + "scale-y", scale, + NULL); + + return TRUE; +} + +int +main (int argc, + char *argv[]) +{ + ClutterActor *stage; + ClutterActor *texture; + gchar *image_path; + GError *error = NULL; + + if (argc < 2) + { + g_print ("Usage: %s \n", argv[0]); + exit (EXIT_FAILURE); + } + + image_path = argv[1]; + + clutter_init (&argc, &argv); + + stage = clutter_stage_get_default (); + clutter_actor_set_size (stage, STAGE_SIDE, STAGE_SIDE); + clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + texture = clutter_texture_new (); + clutter_actor_set_reactive (texture, TRUE); + clutter_actor_set_width (texture, STAGE_SIDE); + clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (texture), TRUE); + + clutter_actor_add_action (texture, clutter_drag_action_new ()); + + g_object_set (G_OBJECT (texture), + "scale-gravity", CLUTTER_GRAVITY_NORTH_WEST, + NULL); + + clutter_texture_set_from_file (CLUTTER_TEXTURE (texture), image_path, &error); + + if (error != NULL) + { + g_warning ("Error loading %s\n%s", image_path, error->message); + g_error_free (error); + exit (EXIT_FAILURE); + } + + clutter_actor_set_y (texture, (STAGE_SIDE - clutter_actor_get_height (texture)) * 0.5); + + g_signal_connect (texture, + "button-release-event", + G_CALLBACK (clicked_cb), + NULL); + + g_signal_connect_swapped (stage, + "key-press-event", + G_CALLBACK (key_press_cb), + texture); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), texture); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} -- 2.7.4