/* Timeline handler */ static void frame_cb (ClutterTimeline *timeline, gint frame_num, gpointer data) { SuperOH *oh = data; gint i; /* Rotate everything clockwise about stage center*/ clutter_actor_set_rotation (CLUTTER_ACTOR (oh->group), CLUTTER_Z_AXIS, frame_num, CLUTTER_STAGE_WIDTH () / 2, CLUTTER_STAGE_HEIGHT () / 2, 0); for (i = 0; i < n_hands; i++) { gdouble scale_x, scale_y; clutter_actor_get_scale (oh->hand[i], &scale_x, &scale_y); /* Rotate each hand around there centers - to get this we need * to take into account any scaling. * * FIXME: scaling causes drift so disabled for now. Need rotation * unit based functions to fix. */ clutter_actor_set_rotation (oh->hand[i], CLUTTER_Z_AXIS, - 6.0 * frame_num, 0, 0, 0); } }
/* 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 == CLUTTER_BUTTON_PRIMARY) scale *= 1.2; else if (button == CLUTTER_BUTTON_SECONDARY) 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; }
static gboolean clutter_zoom_action_real_zoom (ClutterZoomAction *action, ClutterActor *actor, ClutterPoint *focal_point, gdouble factor) { ClutterZoomActionPrivate *priv = action->priv; gfloat x, y, z; gdouble scale_x, scale_y; ClutterVertex out, in; in.x = priv->transformed_focal_point.x; in.y = priv->transformed_focal_point.y; in.z = 0; clutter_actor_apply_transform_to_point (actor, &in, &out); clutter_actor_get_scale (actor, &scale_x, &scale_y); switch (priv->zoom_axis) { case CLUTTER_ZOOM_BOTH: clutter_actor_set_scale (actor, factor, factor); break; case CLUTTER_ZOOM_X_AXIS: clutter_actor_set_scale (actor, factor, scale_y); break; case CLUTTER_ZOOM_Y_AXIS: clutter_actor_set_scale (actor, scale_x, factor); break; default: break; } x = priv->initial_x + priv->focal_point.x - priv->initial_focal_point.x; y = priv->initial_y + priv->focal_point.y - priv->initial_focal_point.y; clutter_actor_get_translation (actor, NULL, NULL, &z); clutter_actor_set_translation (actor, x, y, z); return TRUE; }
static gboolean clutter_zoom_action_gesture_begin (ClutterGestureAction *action, ClutterActor *actor) { ClutterZoomActionPrivate *priv = ((ClutterZoomAction *) action)->priv; gfloat dx, dy; capture_point_initial_position (action, actor, 0, &priv->points[0]); capture_point_initial_position (action, actor, 1, &priv->points[1]); dx = priv->points[1].transformed_start_x - priv->points[0].transformed_start_x; dy = priv->points[1].transformed_start_y - priv->points[0].transformed_start_y; priv->zoom_initial_distance = sqrt (dx * dx + dy * dy); clutter_actor_get_translation (actor, &priv->initial_x, &priv->initial_y, &priv->initial_z); clutter_actor_get_scale (actor, &priv->initial_scale_x, &priv->initial_scale_y); priv->initial_focal_point.x = (priv->points[0].start_x + priv->points[1].start_x) / 2; priv->initial_focal_point.y = (priv->points[0].start_y + priv->points[1].start_y) / 2; clutter_actor_transform_stage_point (actor, priv->initial_focal_point.x, priv->initial_focal_point.y, &priv->transformed_focal_point.x, &priv->transformed_focal_point.y); clutter_actor_set_pivot_point (actor, priv->transformed_focal_point.x / clutter_actor_get_width (actor), priv->transformed_focal_point.y / clutter_actor_get_height (actor)); return TRUE; }