~oem-solutions-group/unity-2d/clutter-1.0

« back to all changes in this revision

Viewing changes to clutter/clutter-animation.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2010-03-21 13:27:56 UTC
  • mto: (2.1.3 experimental)
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20100321132756-nf8yd30yxo3zzwcm
Tags: upstream-1.2.2
ImportĀ upstreamĀ versionĀ 1.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
68
68
 * a #ClutterAnimation instance and animate an actor between its current
69
69
 * state and the specified final state.
70
70
 *
 
71
 * <refsect2 id="clutter-AnimationMode-Script">
 
72
 *   <title>Defining ClutterAnimationMode inside ClutterScript</title>
 
73
 *   <para>When defining a #ClutterAnimation inside a ClutterScript
 
74
 *   file or string the #ClutterAnimation:mode can be defined either
 
75
 *   using the #ClutterAnimationMode enumeration values through their
 
76
 *   "nick" (the short string used inside #GEnumValue), their numeric
 
77
 *   id, or using the following strings:</para>
 
78
 *   <variablelist>
 
79
 *     <varlistentry>
 
80
 *       <term>easeInQuad, easeOutQuad, easeInOutQuad</term>
 
81
 *       <listitem><para>Corresponding to the quadratic easing
 
82
 *       modes</para></listitem>
 
83
 *     </varlistentry>
 
84
 *     <varlistentry>
 
85
 *       <term>easeInCubic, easeOutCubic, easeInOutCubic</term>
 
86
 *       <listitem><para>Corresponding to the cubic easing
 
87
 *       modes</para></listitem>
 
88
 *     </varlistentry>
 
89
 *     <varlistentry>
 
90
 *       <term>easeInQuart, easeOutQuart, easeInOutQuart</term>
 
91
 *       <listitem><para>Corresponding to the quartic easing
 
92
 *       modes</para></listitem>
 
93
 *     </varlistentry>
 
94
 *     <varlistentry>
 
95
 *       <term>easeInQuint, easeOutQuint, easeInOutQuint</term>
 
96
 *       <listitem><para>Corresponding to the quintic easing
 
97
 *       modes</para></listitem>
 
98
 *     </varlistentry>
 
99
 *     <varlistentry>
 
100
 *       <term>easeInSine, easeOutSine, easeInOutSine</term>
 
101
 *       <listitem><para>Corresponding to the sine easing
 
102
 *       modes</para></listitem>
 
103
 *     </varlistentry>
 
104
 *     <varlistentry>
 
105
 *       <term>easeInExpo, easeOutExpo, easeInOutExpo</term>
 
106
 *       <listitem><para>Corresponding to the exponential easing
 
107
 *       modes</para></listitem>
 
108
 *     </varlistentry>
 
109
 *     <varlistentry>
 
110
 *       <term>easeInCirc, easeOutCirc, easeInOutCirc</term>
 
111
 *       <listitem><para>Corresponding to the circular easing
 
112
 *       modes</para></listitem>
 
113
 *     </varlistentry>
 
114
 *     <varlistentry>
 
115
 *       <term>easeInElastic, easeOutElastic, easeInOutElastic</term>
 
116
 *       <listitem><para>Corresponding to the overshooting elastic
 
117
 *       easing modes</para></listitem>
 
118
 *     </varlistentry>
 
119
 *     <varlistentry>
 
120
 *       <term>easeInBack, easeOutBack, easeInOutBack</term>
 
121
 *       <listitem><para>Corresponding to the overshooting cubic
 
122
 *       easing modes</para></listitem>
 
123
 *     </varlistentry>
 
124
 *     <varlistentry>
 
125
 *       <term>easeInBounce, easeOutBounce, easeInOutBounce</term>
 
126
 *       <listitem><para>Corresponding to the bouncing easing
 
127
 *       modes</para></listitem>
 
128
 *     </varlistentry>
 
129
 *   </variablelist>
 
130
 * </refsect2>
 
131
 *
71
132
 * #ClutterAnimation is available since Clutter 1.0
72
133
 */
73
134
 
85
146
#include "clutter-enum-types.h"
86
147
#include "clutter-interval.h"
87
148
#include "clutter-private.h"
 
149
#include "clutter-scriptable.h"
 
150
#include "clutter-script-private.h"
88
151
 
89
152
enum
90
153
{
125
188
 
126
189
static GQuark quark_object_animation = 0;
127
190
 
128
 
G_DEFINE_TYPE (ClutterAnimation, clutter_animation, G_TYPE_OBJECT);
 
191
static void clutter_scriptable_init (ClutterScriptableIface *iface);
 
192
 
 
193
G_DEFINE_TYPE_WITH_CODE (ClutterAnimation, clutter_animation, G_TYPE_OBJECT,
 
194
                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE,
 
195
                                                clutter_scriptable_init));
 
196
 
 
197
static void
 
198
on_actor_dispose (gpointer  user_data,
 
199
                  GObject  *actor_pointer)
 
200
{
 
201
  ClutterAnimation *self = user_data;
 
202
 
 
203
  if (self->priv->object == actor_pointer)
 
204
    {
 
205
      CLUTTER_NOTE (ANIMATION, "Object [%p] was unref'd", actor_pointer);
 
206
      g_object_unref (self);
 
207
    }
 
208
}
 
209
 
129
210
 
130
211
static void
131
212
clutter_animation_real_completed (ClutterAnimation *self)
141
222
  direction = clutter_timeline_get_direction (timeline);
142
223
 
143
224
  /* explicitly set the final state of the animation */
 
225
  CLUTTER_NOTE (ANIMATION, "Set final state on object [%p]", priv->object);
144
226
  g_hash_table_iter_init (&iter, priv->properties);
145
227
  while (g_hash_table_iter_next (&iter, &key, &value))
146
228
    {
167
249
  animation = g_object_get_qdata (priv->object, quark_object_animation);
168
250
  if (animation == self)
169
251
    {
 
252
      CLUTTER_NOTE (ANIMATION, "Unsetting animation for actor [%p]",
 
253
                    priv->object);
 
254
 
170
255
      g_object_set_qdata (priv->object, quark_object_animation, NULL);
 
256
      g_object_weak_unref (priv->object, on_actor_dispose, self);
 
257
 
 
258
      CLUTTER_NOTE (ANIMATION, "Releasing the reference Animation [%p]",
 
259
                    animation);
171
260
      g_object_unref (animation);
172
261
    }
173
262
}
177
266
{
178
267
  ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv;
179
268
 
180
 
  CLUTTER_NOTE (ANIMATION, "Destroying properties hash table");
 
269
  CLUTTER_NOTE (ANIMATION,
 
270
                "Destroying properties table for Animation [%p]",
 
271
                gobject);
181
272
  g_hash_table_destroy (priv->properties);
182
273
 
183
274
  G_OBJECT_CLASS (clutter_animation_parent_class)->finalize (gobject);
303
394
    }
304
395
}
305
396
 
 
397
static gboolean
 
398
clutter_animation_parse_custom_node (ClutterScriptable *scriptable,
 
399
                                     ClutterScript     *script,
 
400
                                     GValue            *value,
 
401
                                     const gchar       *name,
 
402
                                     JsonNode          *node)
 
403
{
 
404
  if (strncmp (name, "mode", 4) == 0)
 
405
    {
 
406
      gulong mode;
 
407
 
 
408
      mode = clutter_script_resolve_animation_mode (node);
 
409
 
 
410
      g_value_init (value, G_TYPE_ULONG);
 
411
      g_value_set_ulong (value, mode);
 
412
 
 
413
      return TRUE;
 
414
    }
 
415
 
 
416
  return FALSE;
 
417
}
 
418
 
 
419
static void
 
420
clutter_scriptable_init (ClutterScriptableIface *iface)
 
421
{
 
422
  iface->parse_custom_node = clutter_animation_parse_custom_node;
 
423
}
 
424
 
306
425
static void
307
426
clutter_animation_class_init (ClutterAnimationClass *klass)
308
427
{
322
441
  gobject_class->finalize = clutter_animation_finalize;
323
442
 
324
443
  /**
325
 
   * ClutterAnimation:objct:
 
444
   * ClutterAnimation:object:
326
445
   *
327
446
   * The #GObject to which the animation applies.
328
447
   *
507
626
  ClutterAnimationPrivate *priv;
508
627
  GObjectClass *klass;
509
628
  GParamSpec *pspec;
 
629
  GType pspec_type;
510
630
 
511
631
  priv = animation->priv;
512
632
 
545
665
      return NULL;
546
666
    }
547
667
 
548
 
  if (!g_value_type_compatible (G_PARAM_SPEC_VALUE_TYPE (pspec),
549
 
                                argtype))
 
668
  pspec_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
 
669
 
 
670
  if (!g_value_type_compatible (argtype, pspec_type) ||
 
671
      !g_value_type_transformable (argtype, pspec_type))
550
672
    {
551
673
      g_warning ("Cannot bind property '%s': the interval value of "
552
674
                 "type '%s' is not compatible with the property value "
553
675
                 "of type '%s'",
554
676
                 property_name,
555
677
                 g_type_name (argtype),
556
 
                 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
 
678
                 g_type_name (pspec_type));
557
679
      return NULL;
558
680
    }
 
681
 
559
682
  return pspec;
560
683
}
561
684
 
632
755
  priv = animation->priv;
633
756
 
634
757
  type = G_VALUE_TYPE (final);
635
 
  pspec = clutter_animation_validate_bind (animation, property_name,
636
 
                                           type);
 
758
  pspec = clutter_animation_validate_bind (animation, property_name, type);
637
759
  if (pspec == NULL)
638
760
    return NULL;
639
761
 
725
847
  ClutterAnimationPrivate *priv;
726
848
  GObjectClass *klass;
727
849
  GParamSpec *pspec;
 
850
  GType pspec_type, int_type;
728
851
 
729
852
  g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
730
853
  g_return_if_fail (property_name != NULL);
751
874
      return;
752
875
    }
753
876
 
754
 
  if (!g_value_type_compatible (G_PARAM_SPEC_VALUE_TYPE (pspec),
755
 
                                clutter_interval_get_value_type (interval)))
 
877
  pspec_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
 
878
  int_type = clutter_interval_get_value_type (interval);
 
879
 
 
880
  if (!g_value_type_compatible (int_type, pspec_type) ||
 
881
      !g_value_type_transformable (int_type, pspec_type))
756
882
    {
757
883
      g_warning ("Cannot update property '%s': the interval value of "
758
884
                 "type '%s' is not compatible with the property value "
759
885
                 "of type '%s'",
760
886
                 property_name,
761
 
                 g_type_name (clutter_interval_get_value_type (interval)),
762
 
                 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
 
887
                 g_type_name (int_type),
 
888
                 g_type_name (pspec_type));
763
889
      return;
764
890
    }
765
891
 
767
893
}
768
894
 
769
895
/**
 
896
 * clutter_animation_update:
 
897
 * @animation: a #ClutterAnimation
 
898
 * @property_name: name of the property
 
899
 * @final: The final value of the property
 
900
 *
 
901
 * Updates the @final value of the interval for @property_name
 
902
 *
 
903
 * Return value: (transfer none): The animation itself.
 
904
 *
 
905
 * Since: 1.0
 
906
 */
 
907
ClutterAnimation *
 
908
clutter_animation_update (ClutterAnimation *animation,
 
909
                          const gchar      *property_name,
 
910
                          const GValue     *final)
 
911
{
 
912
  ClutterInterval *interval;
 
913
  GType int_type;
 
914
 
 
915
  g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL);
 
916
  g_return_val_if_fail (property_name != NULL, NULL);
 
917
  g_return_val_if_fail (final != NULL, NULL);
 
918
  g_return_val_if_fail (G_VALUE_TYPE (final) != G_TYPE_INVALID, NULL);
 
919
 
 
920
  interval = clutter_animation_get_interval (animation, property_name);
 
921
  if (interval == NULL)
 
922
    {
 
923
      g_warning ("Cannot update property '%s': the animation has "
 
924
                 "no bound property with that name",
 
925
                 property_name);
 
926
      return NULL;
 
927
    }
 
928
 
 
929
  int_type = clutter_interval_get_value_type (interval);
 
930
 
 
931
  if (!g_value_type_compatible (G_VALUE_TYPE (final), int_type) ||
 
932
      !g_value_type_transformable (G_VALUE_TYPE (final), int_type))
 
933
    {
 
934
      g_warning ("Cannot update property '%s': the interval value of "
 
935
                 "type '%s' is not compatible with the property value "
 
936
                 "of type '%s'",
 
937
                 property_name,
 
938
                 g_type_name (int_type),
 
939
                 g_type_name (G_VALUE_TYPE (final)));
 
940
      return NULL;
 
941
    }
 
942
 
 
943
  clutter_interval_set_final_value (interval, final);
 
944
 
 
945
  return animation;
 
946
}
 
947
 
 
948
/**
770
949
 * clutter_animation_get_interval:
771
950
 * @animation: a #ClutterAnimation
772
951
 * @property_name: name of the property
1047
1226
  g_object_freeze_notify (G_OBJECT (animation));
1048
1227
 
1049
1228
  alpha = clutter_animation_get_alpha_internal (animation);
 
1229
  g_assert (CLUTTER_IS_ALPHA (alpha));
 
1230
 
1050
1231
  clutter_alpha_set_mode (alpha, mode);
1051
1232
 
1052
1233
  g_object_notify (G_OBJECT (animation), "mode");
1100
1281
  g_object_freeze_notify (G_OBJECT (animation));
1101
1282
 
1102
1283
  timeline = clutter_animation_get_timeline_internal (animation);
 
1284
  g_assert (CLUTTER_IS_TIMELINE (timeline));
 
1285
 
1103
1286
  clutter_timeline_set_duration (timeline, msecs);
1104
1287
  clutter_timeline_rewind (timeline);
1105
1288
 
1350
1533
                          animation);
1351
1534
    }
1352
1535
  else
1353
 
    timeline = clutter_animation_get_timeline_internal (animation);
 
1536
    {
 
1537
      /* FIXME - add a create_timeline_internal() because this does
 
1538
       * not look very good
 
1539
       */
 
1540
      (void) clutter_animation_get_timeline_internal (animation);
 
1541
    }
1354
1542
 
1355
1543
out:
1356
1544
  /* emit all relevant notifications */
1460
1648
   */
1461
1649
  if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (&real_value)))
1462
1650
    {
1463
 
      if (!g_value_type_compatible (G_VALUE_TYPE (value),
1464
 
                                    G_VALUE_TYPE (&real_value)) &&
1465
 
          !g_value_type_compatible (G_VALUE_TYPE (&real_value),
1466
 
                                    G_VALUE_TYPE (value)))
1467
 
        {
1468
 
          g_warning ("%s: Unable to convert from %s to %s for "
1469
 
                     "the property '%s' of object %s",
1470
 
                     G_STRLOC,
1471
 
                     g_type_name (G_VALUE_TYPE (value)),
1472
 
                     g_type_name (G_VALUE_TYPE (&real_value)),
1473
 
                     property_name,
1474
 
                     G_OBJECT_TYPE_NAME (priv->object));
1475
 
          g_value_unset (&real_value);
1476
 
          return;
1477
 
        }
1478
 
 
1479
 
      if (!g_value_transform (value, &real_value))
1480
 
        {
1481
 
          g_warning ("%s: Unable to transform from %s to %s",
1482
 
                     G_STRLOC,
1483
 
                     g_type_name (G_VALUE_TYPE (value)),
1484
 
                     g_type_name (G_VALUE_TYPE (&real_value)));
1485
 
          g_value_unset (&real_value);
1486
 
          return;
1487
 
        }
 
1651
      /* are these two types compatible (can be directly copied)? */
 
1652
      if (g_value_type_compatible (G_VALUE_TYPE (value),
 
1653
                                   G_VALUE_TYPE (&real_value)))
 
1654
        {
 
1655
          g_value_copy (value, &real_value);
 
1656
          goto done;
 
1657
        }
 
1658
 
 
1659
      /* are these two type transformable? */
 
1660
      if (g_value_type_transformable (G_VALUE_TYPE (value),
 
1661
                                      G_VALUE_TYPE (&real_value)))
 
1662
        {
 
1663
          if (g_value_transform (value, &real_value))
 
1664
            goto done;
 
1665
        }
 
1666
 
 
1667
      /* if not compatible and not transformable then we can't do much */
 
1668
      g_warning ("%s: Unable to convert from %s to %s for "
 
1669
                 "the property '%s' of object %s",
 
1670
                 G_STRLOC,
 
1671
                 g_type_name (G_VALUE_TYPE (value)),
 
1672
                 g_type_name (G_VALUE_TYPE (&real_value)),
 
1673
                 property_name,
 
1674
                 G_OBJECT_TYPE_NAME (priv->object));
 
1675
      g_value_unset (&real_value);
 
1676
      return;
1488
1677
    }
1489
1678
  else
1490
1679
    g_value_copy (value, &real_value);
1491
1680
 
 
1681
done:
1492
1682
  /* create an interval and bind it to the property, in case
1493
1683
   * it's not a fixed property, otherwise just set it
1494
1684
   */
1647
1837
              break;
1648
1838
            }
1649
1839
 
 
1840
#if GLIB_CHECK_VERSION (2, 23, 2)
 
1841
          G_VALUE_COLLECT_INIT (&final, G_PARAM_SPEC_VALUE_TYPE (pspec),
 
1842
                                var_args, 0,
 
1843
                                &error);
 
1844
#else
 
1845
          /* this is the same as G_VALUE_COLLECT_INIT(), but slower */
1650
1846
          g_value_init (&final, G_PARAM_SPEC_VALUE_TYPE (pspec));
1651
1847
          G_VALUE_COLLECT (&final, var_args, 0, &error);
 
1848
#endif /* GLIB_CHECK_VERSION (2, 23, 2) */
 
1849
 
1652
1850
          if (error)
1653
1851
            {
1654
1852
              g_warning ("%s: %s", G_STRLOC, error);
1678
1876
      animation = clutter_animation_new ();
1679
1877
      clutter_animation_set_object (animation, object);
1680
1878
      g_object_set_qdata (object, quark_object_animation, animation);
 
1879
      g_object_weak_ref (object, on_actor_dispose, animation);
1681
1880
 
1682
1881
      CLUTTER_NOTE (ANIMATION,
1683
1882
                    "Created new Animation [%p] for actor [%p]",
1851
2050
 * to control the animation or to know when the animation has been
1852
2051
 * completed.
1853
2052
 *
1854
 
 * If a name argument starts with "signal::", "signal-after::" or
1855
 
 * "signal-swapped::" the two following arguments are used as callback
1856
 
 * function and data for a signal handler installed on the
1857
 
 * #ClutterAnimation object for the specified signal name, for
1858
 
 * instance:
 
2053
 * If a name argument starts with "signal::", "signal-after::",
 
2054
 * "signal-swapped::" or "signal-swapped-after::" the two following arguments
 
2055
 * are used as callback function and data for a signal handler installed on
 
2056
 * the #ClutterAnimation object for the specified signal name, for instance:
1859
2057
 *
1860
2058
 * |[
1861
2059
 *
1872
2070
 *                          NULL);
1873
2071
 * ]|
1874
2072
 *
 
2073
 * or, to automatically destroy an actor at the end of the animation:
 
2074
 *
 
2075
 * |[
 
2076
 *   clutter_actor_animate (actor, CLUTTER_EASE_IN_CUBIC, 100,
 
2077
 *                          "opacity", 0,
 
2078
 *                          "signal-swapped-after::completed",
 
2079
 *                            clutter_actor_destroy,
 
2080
 *                            actor,
 
2081
 *                          NULL);
 
2082
 * ]|
 
2083
 *
1875
2084
 * The "signal::" modifier is the equivalent of using g_signal_connect();
1876
2085
 * the "signal-after::" modifier is the equivalent of using
1877
 
 * g_signal_connect_after(); the "signal-swapped::" modifier is the equivalent
1878
 
 * of using g_signal_connect_swapped(). The clutter_actor_animate() function
1879
 
 * will not keep track of multiple connections to the same signal, so it is
1880
 
 * your responsability to avoid them when calling clutter_actor_animate()
1881
 
 * multiple times on the same actor.
 
2086
 * g_signal_connect_after() or g_signal_connect_data() with the
 
2087
 * %G_CONNECT_AFTER; the "signal-swapped::" modifier is the equivalent
 
2088
 * of using g_signal_connect_swapped() or g_signal_connect_data() with the
 
2089
 * %G_CONNECT_SWAPPED flah; finally, the "signal-swapped-after::" modifier
 
2090
 * is the equivalent of using g_signal_connect_data() with both the
 
2091
 * %G_CONNECT_AFTER and %G_CONNECT_SWAPPED flags. The clutter_actor_animate()
 
2092
 * function will not keep track of multiple connections to the same signal,
 
2093
 * so it is your responsability to avoid them when calling
 
2094
 * clutter_actor_animate() multiple times on the same actor.
1882
2095
 *
1883
2096
 * Calling this function on an actor that is already being animated
1884
2097
 * will cause the current animation to change with the new final values,