static ClutterAlpha *
layout_manager_real_begin_animation (ClutterLayoutManager *manager,
                                     guint                 duration,
                                     gulong                mode)
{
    ClutterTimeline *timeline;
    ClutterAlpha *alpha;

    alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
    if (alpha != NULL)
    {
        clutter_alpha_set_mode (alpha, mode);

        timeline = clutter_alpha_get_timeline (alpha);
        clutter_timeline_set_duration (timeline, duration);
        clutter_timeline_rewind (timeline);

        return alpha;
    };

    timeline = clutter_timeline_new (duration);

    alpha = clutter_alpha_new_full (timeline, mode);

    /* let the alpha take ownership of the timeline */
    g_object_unref (timeline);

    g_signal_connect_swapped (timeline, "completed",
                              G_CALLBACK (clutter_layout_manager_end_animation),
                              manager);
    g_signal_connect_swapped (timeline, "new-frame",
                              G_CALLBACK (clutter_layout_manager_layout_changed),
                              manager);

    g_object_set_qdata_full (G_OBJECT (manager),
                             quark_layout_alpha, alpha,
                             (GDestroyNotify) g_object_unref);

    clutter_timeline_start (timeline);

    return alpha;
}
Exemple #2
0
static void
interpolation_completed_cb (ClutterTimeline *timeline,
                            MxAdjustment    *adjustment)
{
  MxAdjustmentPrivate *priv = adjustment->priv;

  if (priv->elastic && priv->clamp_value)
    {
      if (clutter_timeline_get_direction (priv->interpolation) ==
            CLUTTER_TIMELINE_FORWARD)
        {
          clutter_timeline_set_direction (priv->interpolation,
                                          CLUTTER_TIMELINE_BACKWARD);
          clutter_timeline_set_duration (priv->interpolation, 250);
          clutter_timeline_rewind (priv->interpolation);

          if (priv->new_position < priv->lower)
            {
              priv->old_position = priv->lower;
              clutter_timeline_start (priv->interpolation);
            }
          else if (priv->new_position > (priv->upper - priv->page_size))
            {
              priv->old_position = priv->upper - priv->page_size;
              clutter_timeline_start (priv->interpolation);
            }
        }
      else
        {
          stop_interpolation (adjustment);
          mx_adjustment_set_value (adjustment, priv->old_position);
        }
    }
  else
    {
      stop_interpolation (adjustment);
      mx_adjustment_set_value (adjustment, priv->new_position);
    }

  g_signal_emit (adjustment, signals[INTERPOLATION_COMPLETED], 0);
}
Exemple #3
0
void
mex_tile_set_important (MexTile  *tile,
                        gboolean  important)
{
  MexTilePrivate *priv;

  g_return_if_fail (MEX_IS_TILE (tile));

  priv = tile->priv;
  if (priv->important != important)
    {
      priv->important = important;

      g_object_notify (G_OBJECT (tile), "important");

      mx_stylable_set_style_class (MX_STYLABLE (tile),
                                   important ? "Important" : NULL);

      if (clutter_timeline_is_playing (priv->timeline))
        clutter_timeline_set_direction (priv->timeline, important ?
                                        CLUTTER_TIMELINE_FORWARD :
                                        CLUTTER_TIMELINE_BACKWARD);
      else
        {
          if (CLUTTER_ACTOR_IS_MAPPED (tile))
            {
              clutter_timeline_rewind (priv->timeline);
              clutter_timeline_start (priv->timeline);
            }
          else
            {
              clutter_timeline_advance (priv->timeline, DURATION);
              mex_tile_important_new_frame_cb (priv->timeline, 0, tile);
              mex_tile_timeline_completed_cb (priv->timeline, tile);
            }
        }
    }
}
Exemple #4
0
static void
mx_expander_update (MxExpander *expander)
{
  MxExpanderPrivate *priv = expander->priv;
  ClutterActor *child;

  if (priv->expanded)
    {
      clutter_actor_set_name (priv->arrow, "mx-expander-arrow-open");
      mx_stylable_set_style_class (MX_STYLABLE (expander), "open-expander");
    }
  /* closed state is set when animation is finished */

  child = mx_bin_get_child (MX_BIN (expander));

  if (!child)
    return;

  /* setup and start the expansion animation */
  if (!priv->expanded)
    {
      clutter_actor_hide (child);
      clutter_timeline_set_direction (priv->timeline,
                                      CLUTTER_TIMELINE_BACKWARD);
    }
  else
    {
      clutter_timeline_set_direction (priv->timeline,
                                      CLUTTER_TIMELINE_FORWARD);
    }


  if (!clutter_timeline_is_playing (priv->timeline))
    clutter_timeline_rewind (priv->timeline);

  clutter_timeline_start (priv->timeline);
}
static void
mx_label_allocate (ClutterActor          *actor,
                   const ClutterActorBox *box,
                   ClutterAllocationFlags flags)
{
  MxLabelPrivate *priv = MX_LABEL (actor)->priv;
  gboolean label_did_fade = priv->label_should_fade;

  ClutterActorClass *parent_class;
  ClutterActorBox child_box;
  gboolean x_fill, y_fill;
  gfloat avail_width;

  parent_class = CLUTTER_ACTOR_CLASS (mx_label_parent_class);
  parent_class->allocate (actor, box, flags);

  mx_widget_get_available_area (MX_WIDGET (actor), box, &child_box);
  avail_width = child_box.x2 - child_box.x1;

  /* The default behaviour of ClutterText is to align to the
   * top-left when it gets more space than is needed. Because
   * of this behaviour, if we're aligning to the left, we can
   * assign all our horizontal space to the label without
   * measuring it (i.e. x-fill), and the same applies for
   * aligning to the top and vertical space.
   */
  x_fill = (priv->x_align == MX_ALIGN_START) ? TRUE : FALSE;
  y_fill = (priv->y_align == MX_ALIGN_START) ? TRUE : FALSE;

  mx_allocate_align_fill (priv->label, &child_box, priv->x_align,
                          priv->y_align, x_fill, y_fill);

  priv->label_should_fade = FALSE;

  if (priv->fade_out)
    {
      /* If we're fading out, make sure the label has its full width
       * allocated. This ensures that the offscreen effect has the full
       * label inside its texture.
       */
      gfloat label_width;

      clutter_actor_get_preferred_width (priv->label, -1, NULL, &label_width);

      if (label_width > avail_width)
        {
          priv->label_should_fade = TRUE;
          child_box.x2 = child_box.x1 + label_width;
        }

      mx_fade_effect_set_bounds (MX_FADE_EFFECT (priv->fade_effect),
                                 0, 0, MIN (label_width, avail_width), 0);
    }

  /* Allocate the label */
  clutter_actor_allocate (priv->label, &child_box, flags);

  if (priv->show_tooltip)
    {
      PangoLayout *layout;
      const gchar *text;

      layout = clutter_text_get_layout (CLUTTER_TEXT (priv->label));

      if (pango_layout_is_ellipsized (layout))
        text = clutter_text_get_text (CLUTTER_TEXT (priv->label));
      else
        text = NULL;

      mx_widget_set_tooltip_text (MX_WIDGET (actor), text);
    }

  /* Animate in/out the faded end of the label */
  if (label_did_fade != priv->label_should_fade)
    {
      /* Begin/reverse the fading timeline when necessary */
      if (priv->label_should_fade)
        clutter_timeline_set_direction (priv->fade_timeline,
                                        CLUTTER_TIMELINE_FORWARD);
      else
        clutter_timeline_set_direction (priv->fade_timeline,
                                        CLUTTER_TIMELINE_BACKWARD);

      if (!clutter_timeline_is_playing (priv->fade_timeline))
        clutter_timeline_rewind (priv->fade_timeline);

      clutter_timeline_start (priv->fade_timeline);
    }
}
Exemple #6
0
/**
 * clutter_timeline_stop:
 * @timeline: A #ClutterTimeline
 *
 * Stops the #ClutterTimeline and moves to frame 0
 **/
void
clutter_timeline_stop (ClutterTimeline *timeline)
{
  clutter_timeline_pause (timeline);
  clutter_timeline_rewind (timeline);
}
Exemple #7
0
static gboolean
clutter_timeline_do_frame (ClutterTimeline *timeline)
{
  ClutterTimelinePrivate *priv;

  priv = timeline->priv;

  g_object_ref (timeline);

  CLUTTER_TIMESTAMP (SCHEDULER, "Timeline [%p] activated (cur: %ld)\n",
                     timeline,
                     (long) priv->elapsed_time);

  /* Advance time */
  if (priv->direction == CLUTTER_TIMELINE_FORWARD)
    priv->elapsed_time += priv->msecs_delta;
  else
    priv->elapsed_time -= priv->msecs_delta;

  /* If we have not reached the end of the timeline: */
  if (!is_complete (timeline))
    {
      /* Emit the signal */
      emit_frame_signal (timeline);
      check_markers (timeline, priv->msecs_delta);

      /* Signal pauses timeline ? */
      if (!priv->is_playing)
        {
          g_object_unref (timeline);
          return FALSE;
        }

      g_object_unref (timeline);
      return TRUE;
    }
  else
    {
      /* Handle loop or stop */
      ClutterTimelineDirection saved_direction = priv->direction;
      gint elapsed_time_delta = priv->msecs_delta;
      guint overflow_msecs = priv->elapsed_time;
      gint end_msecs;

      /* Update the current elapsed time in case the signal handlers
       * want to take a peek. If we clamp elapsed time, then we need
       * to correpondingly reduce elapsed_time_delta to reflect the correct
       * range of times */
      if (priv->direction == CLUTTER_TIMELINE_FORWARD)
	{
	  elapsed_time_delta -= (priv->elapsed_time - priv->duration);
	  priv->elapsed_time = priv->duration;
	}
      else if (priv->direction == CLUTTER_TIMELINE_BACKWARD)
	{
	  elapsed_time_delta -= - priv->elapsed_time;
	  priv->elapsed_time = 0;
	}

      end_msecs = priv->elapsed_time;

      /* Emit the signal */
      emit_frame_signal (timeline);
      check_markers (timeline, elapsed_time_delta);

      /* Did the signal handler modify the elapsed time? */
      if (priv->elapsed_time != end_msecs)
        {
          g_object_unref (timeline);
          return TRUE;
        }

      /* Note: If the new-frame signal handler paused the timeline
       * on the last frame we will still go ahead and send the
       * completed signal */
      CLUTTER_NOTE (SCHEDULER,
                    "Timeline [%p] completed (cur: %ld, tot: %ld)",
                    timeline,
                    (long) priv->elapsed_time,
                    (long) priv->msecs_delta);

      if (!priv->loop && priv->is_playing)
        {
          /* We remove the timeout now, so that the completed signal handler
           * may choose to re-start the timeline
           *
           * XXX Perhaps we should remove this earlier, and regardless
           * of priv->loop. Are we limiting the things that could be done in
           * the above new-frame signal handler */
	  set_is_playing (timeline, FALSE);
        }

      g_signal_emit (timeline, timeline_signals[COMPLETED], 0);

      /* Again check to see if the user has manually played with
       * the elapsed time, before we finally stop or loop the timeline */

      if (priv->elapsed_time != end_msecs &&
          !(/* Except allow changing time from 0 -> duration (or vice-versa)
               since these are considered equivalent */
            (priv->elapsed_time == 0 && end_msecs == priv->duration) ||
            (priv->elapsed_time == priv->duration && end_msecs == 0)
          ))
        {
          g_object_unref (timeline);
          return TRUE;
        }

      if (priv->loop)
        {
          /* We try and interpolate smoothly around a loop */
          if (saved_direction == CLUTTER_TIMELINE_FORWARD)
            priv->elapsed_time = overflow_msecs - priv->duration;
          else
            priv->elapsed_time = priv->duration + overflow_msecs;

          /* Or if the direction changed, we try and bounce */
          if (priv->direction != saved_direction)
            priv->elapsed_time = priv->duration - priv->elapsed_time;

          /* If we have overflowed then we are changing the elapsed
             time without emitting the new frame signal so we need to
             check for markers again */
          check_markers (timeline,
                         priv->direction == CLUTTER_TIMELINE_FORWARD ?
                         priv->elapsed_time :
                         priv->duration - priv->elapsed_time);

          g_object_unref (timeline);
          return TRUE;
        }
      else
        {
          clutter_timeline_rewind (timeline);

          g_object_unref (timeline);
          return FALSE;
        }
    }
}
Exemple #8
0
void
aisleriot_slot_renderer_set_animations (AisleriotSlotRenderer *srend,
                                        guint n_anims,
                                        const AisleriotAnimStart *anims,
                                        guint n_unexposed_animated_cards)
{
  AisleriotSlotRendererPrivate *priv;
  guint i;
  gint card_num;

  g_return_if_fail (AISLERIOT_IS_SLOT_RENDERER (srend));

  priv = srend->priv;

  g_return_if_fail (n_anims <= priv->slot->exposed);

  /* Destroy the current animations */
  for (i = 0; i < priv->animations->len; i++) {
    AnimationData *anim_data;

    anim_data = &g_array_index (priv->animations, AnimationData, i);

    if (anim_data->move)
      g_object_unref (anim_data->move);
    if (anim_data->rotate)
      g_object_unref (anim_data->rotate);
    if (anim_data->depth)
      g_object_unref (anim_data->depth);

    clutter_actor_destroy (anim_data->card_tex);
    g_object_unref (anim_data->card_tex);
  }

  g_array_set_size (priv->animations, 0);

  card_num = priv->slot->cards->len - n_anims;

  for (i = 0; i < n_anims; i++) {
    AnimationData anim_data;
    ClutterAlpha *alpha;
    ClutterKnot knots[2];
    Card card = CARD (priv->slot->cards->data[card_num]);
    guint card_width, card_height;

    memset (&anim_data, 0, sizeof (anim_data));

    anim_data.card_tex = aisleriot_card_new (priv->cache,
                                             anims[i].old_card,
                                             card);

    card_width = clutter_actor_get_width (anim_data.card_tex);
    card_height = clutter_actor_get_height (anim_data.card_tex);

    g_object_ref_sink (anim_data.card_tex);
    if (priv->animation_layer)
      clutter_container_add (priv->animation_layer,
                             CLUTTER_ACTOR (anim_data.card_tex), NULL);

    clutter_actor_set_position (anim_data.card_tex,
                                anims[i].cardx, anims[i].cardy);

    knots[0].x = anims[i].cardx;
    knots[0].y = anims[i].cardy;

    aisleriot_game_get_card_offset (priv->slot, card_num, FALSE,
                                    &knots[1].x, &knots[1].y);
    knots[1].x += priv->slot->rect.x;
    knots[1].y += priv->slot->rect.y;

    alpha = clutter_alpha_new_full (priv->timeline, CLUTTER_LINEAR);

    anim_data.move
      = clutter_behaviour_path_new_with_knots (alpha, knots,
                                               G_N_ELEMENTS (knots));
    clutter_behaviour_apply (anim_data.move, anim_data.card_tex);

    if (anims[i].old_card.value != card.value) {
      int center_x, center_y;

      center_x = card_width / 2;
      center_y = card_height / 2;

      clutter_actor_set_rotation (anim_data.card_tex, CLUTTER_Y_AXIS,
                                  180.0,
                                  center_x, center_y, 0);

      anim_data.rotate = clutter_behaviour_rotate_new (alpha,
                                                       CLUTTER_Y_AXIS,
                                                       CLUTTER_ROTATE_CW,
                                                       180.0, 0.0);
      clutter_behaviour_rotate_set_center (CLUTTER_BEHAVIOUR_ROTATE
                                           (anim_data.rotate),
                                           center_x, center_y, 0);

      clutter_behaviour_apply (anim_data.rotate, anim_data.card_tex);
    }

    if (anims[i].raise) {
      alpha = clutter_alpha_new_with_func (priv->timeline,
                                           aisleriot_slot_sine_animation_mode,
                                           NULL, NULL);

      anim_data.depth = clutter_behaviour_depth_new (alpha,
                                                     0, card_height);
      clutter_behaviour_apply (anim_data.depth, anim_data.card_tex);
    }

    g_array_append_val (priv->animations, anim_data);

    card_num++;
  }

  if (n_anims > 0) {
    clutter_timeline_rewind (priv->timeline);
    clutter_timeline_start (priv->timeline);
  }

  priv->n_unexposed_animated_cards = n_unexposed_animated_cards;

  clutter_actor_queue_redraw (CLUTTER_ACTOR (srend));
}