4
* An OpenGL based 'interactive canvas' library.
6
* Copyright (C) 2012 Intel Corporation
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2 of the License, or (at your option) any later version.
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
21
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
25
* SECTION:clutter-transition
26
* @Title: ClutterTransition
27
* @Short_Description: Transition between two values
29
* #ClutterTransition is a subclass of #ClutterTimeline that computes
30
* the interpolation between two values, stored by a #ClutterInterval.
37
#include "clutter-transition.h"
39
#include "clutter-animatable.h"
40
#include "clutter-debug.h"
41
#include "clutter-interval.h"
42
#include "clutter-private.h"
43
#include "clutter-timeline.h"
45
struct _ClutterTransitionPrivate
47
ClutterInterval *interval;
48
ClutterAnimatable *animatable;
50
guint remove_on_complete : 1;
59
PROP_REMOVE_ON_COMPLETE,
64
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
66
static GQuark quark_animatable_set = 0;
68
G_DEFINE_ABSTRACT_TYPE (ClutterTransition, clutter_transition, CLUTTER_TYPE_TIMELINE)
71
clutter_transition_attach (ClutterTransition *transition,
72
ClutterAnimatable *animatable)
74
CLUTTER_TRANSITION_GET_CLASS (transition)->attached (transition, animatable);
78
clutter_transition_detach (ClutterTransition *transition,
79
ClutterAnimatable *animatable)
81
CLUTTER_TRANSITION_GET_CLASS (transition)->detached (transition, animatable);
85
clutter_transition_real_compute_value (ClutterTransition *transition,
86
ClutterAnimatable *animatable,
87
ClutterInterval *interval,
93
clutter_transition_real_attached (ClutterTransition *transition,
94
ClutterAnimatable *animatable)
99
clutter_transition_real_detached (ClutterTransition *transition,
100
ClutterAnimatable *animatable)
105
clutter_transition_new_frame (ClutterTimeline *timeline,
106
gint elapsed G_GNUC_UNUSED)
108
ClutterTransition *transition = CLUTTER_TRANSITION (timeline);
109
ClutterTransitionPrivate *priv = transition->priv;
112
if (priv->interval == NULL ||
113
priv->animatable == NULL)
116
progress = clutter_timeline_get_progress (timeline);
118
CLUTTER_TRANSITION_GET_CLASS (timeline)->compute_value (transition,
125
clutter_transition_completed (ClutterTimeline *timeline)
127
ClutterTransitionPrivate *priv = CLUTTER_TRANSITION (timeline)->priv;
129
if (priv->animatable != NULL && priv->remove_on_complete)
131
int n_repeats, cur_repeat;
133
n_repeats = clutter_timeline_get_repeat_count (timeline);
134
cur_repeat = clutter_timeline_get_current_repeat (timeline);
136
if (n_repeats == 0 || cur_repeat == n_repeats)
138
clutter_transition_detach (CLUTTER_TRANSITION (timeline),
140
g_clear_object (&priv->animatable);
141
g_object_unref (timeline);
147
clutter_transition_set_property (GObject *gobject,
152
ClutterTransition *transition = CLUTTER_TRANSITION (gobject);
157
clutter_transition_set_interval (transition, g_value_get_object (value));
160
case PROP_ANIMATABLE:
161
clutter_transition_set_animatable (transition, g_value_get_object (value));
164
case PROP_REMOVE_ON_COMPLETE:
165
clutter_transition_set_remove_on_complete (transition, g_value_get_boolean (value));
169
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
175
clutter_transition_get_property (GObject *gobject,
180
ClutterTransitionPrivate *priv = CLUTTER_TRANSITION (gobject)->priv;
185
g_value_set_object (value, priv->interval);
188
case PROP_ANIMATABLE:
189
g_value_set_object (value, priv->animatable);
192
case PROP_REMOVE_ON_COMPLETE:
193
g_value_set_boolean (value, priv->remove_on_complete);
197
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
203
clutter_transition_dispose (GObject *gobject)
205
ClutterTransitionPrivate *priv = CLUTTER_TRANSITION (gobject)->priv;
207
if (priv->animatable != NULL)
208
clutter_transition_detach (CLUTTER_TRANSITION (gobject),
211
g_clear_object (&priv->interval);
212
g_clear_object (&priv->animatable);
214
G_OBJECT_CLASS (clutter_transition_parent_class)->dispose (gobject);
218
clutter_transition_class_init (ClutterTransitionClass *klass)
220
ClutterTimelineClass *timeline_class = CLUTTER_TIMELINE_CLASS (klass);
221
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
223
quark_animatable_set =
224
g_quark_from_static_string ("-clutter-transition-animatable-set");
226
g_type_class_add_private (klass, sizeof (ClutterTransitionPrivate));
228
klass->compute_value = clutter_transition_real_compute_value;
229
klass->attached = clutter_transition_real_attached;
230
klass->detached = clutter_transition_real_detached;
232
timeline_class->new_frame = clutter_transition_new_frame;
233
timeline_class->completed = clutter_transition_completed;
235
gobject_class->set_property = clutter_transition_set_property;
236
gobject_class->get_property = clutter_transition_get_property;
237
gobject_class->dispose = clutter_transition_dispose;
240
* ClutterTransition:interval:
242
* The #ClutterInterval used to describe the initial and final states
247
obj_props[PROP_INTERVAL] =
248
g_param_spec_object ("interval",
250
P_("The interval of values to transition"),
251
CLUTTER_TYPE_INTERVAL,
253
G_PARAM_STATIC_STRINGS);
256
* ClutterTransition:animatable:
258
* The #ClutterAnimatable instance currently being animated.
262
obj_props[PROP_ANIMATABLE] =
263
g_param_spec_object ("animatable",
265
P_("The animatable object"),
266
CLUTTER_TYPE_ANIMATABLE,
268
G_PARAM_STATIC_STRINGS);
271
* ClutterTransition:remove-on-complete:
273
* Whether the #ClutterTransition should be automatically detached
274
* from the #ClutterTransition:animatable instance whenever the
275
* #ClutterTimeline::completed signal is emitted.
277
* The #ClutterTransition:remove-on-complete property takes into
278
* account the value of the #ClutterTimeline:repeat-count property,
279
* and it only detaches the transition if the transition is not
284
obj_props[PROP_REMOVE_ON_COMPLETE] =
285
g_param_spec_boolean ("remove-on-complete",
286
P_("Remove on Complete"),
287
P_("Detach the transition when completed"),
289
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
291
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
295
clutter_transition_init (ClutterTransition *self)
297
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_TRANSITION,
298
ClutterTransitionPrivate);
302
* clutter_transition_set_interval:
303
* @transition: a #ClutterTransition
304
* @interval: (allow-none): a #ClutterInterval, or %NULL
306
* Sets the #ClutterTransition:interval property using @interval.
308
* The @transition will acquire a reference on the @interval, sinking
309
* the floating flag on it if necessary.
314
clutter_transition_set_interval (ClutterTransition *transition,
315
ClutterInterval *interval)
317
ClutterTransitionPrivate *priv;
319
g_return_if_fail (CLUTTER_IS_TRANSITION (transition));
320
g_return_if_fail (interval == NULL || CLUTTER_IS_INTERVAL (interval));
322
priv = transition->priv;
324
g_clear_object (&priv->interval);
326
if (interval != NULL)
327
priv->interval = g_object_ref_sink (interval);
329
g_object_notify_by_pspec (G_OBJECT (transition), obj_props[PROP_INTERVAL]);
333
* clutter_transition_get_interval:
334
* @transition: a #ClutterTransition
336
* Retrieves the interval set using clutter_transition_set_interval()
338
* Return value: (transfer none): a #ClutterInterval, or %NULL; the returned
339
* interval is owned by the #ClutterTransition and it should not be freed
345
clutter_transition_get_interval (ClutterTransition *transition)
347
g_return_val_if_fail (CLUTTER_IS_TRANSITION (transition), NULL);
349
return transition->priv->interval;
353
* clutter_transition_set_animatable:
354
* @transition: a #ClutterTransition
355
* @animatable: (allow-none): a #ClutterAnimatable, or %NULL
357
* Sets the #ClutterTransition:animatable property.
359
* The @transition will acquire a reference to the @animatable instance,
360
* and will call the #ClutterTransitionClass.attached() virtual function.
362
* If an existing #ClutterAnimatable is attached to @transition, the
363
* reference will be released, and the #ClutterTransitionClass.detached()
364
* virtual function will be called.
369
clutter_transition_set_animatable (ClutterTransition *transition,
370
ClutterAnimatable *animatable)
372
ClutterTransitionPrivate *priv;
374
g_return_if_fail (CLUTTER_IS_TRANSITION (transition));
375
g_return_if_fail (animatable == NULL || CLUTTER_IS_ANIMATABLE (animatable));
377
priv = transition->priv;
379
if (priv->animatable == animatable)
382
if (priv->animatable != NULL)
383
clutter_transition_detach (transition, priv->animatable);
385
g_clear_object (&priv->animatable);
387
if (animatable != NULL)
389
priv->animatable = g_object_ref (animatable);
390
clutter_transition_attach (transition, priv->animatable);
395
* clutter_transition_get_animatable:
396
* @transition: a #ClutterTransition
398
* Retrieves the #ClutterAnimatable set using clutter_transition_set_animatable().
400
* Return value: (transfer none): a #ClutterAnimatable, or %NULL; the returned
401
* animatable is owned by the #ClutterTransition, and it should not be freed
407
clutter_transition_get_animatable (ClutterTransition *transition)
409
g_return_val_if_fail (CLUTTER_IS_TRANSITION (transition), NULL);
411
return transition->priv->animatable;
415
* clutter_transition_set_remove_on_complete:
416
* @transition: a #ClutterTransition
417
* @remove_complete: whether to detach @transition when complete
419
* Sets whether @transition should be detached from the #ClutterAnimatable
420
* set using clutter_transition_set_animatable() when the
421
* #ClutterTimeline::completed signal is emitted.
426
clutter_transition_set_remove_on_complete (ClutterTransition *transition,
427
gboolean remove_complete)
429
g_return_if_fail (CLUTTER_IS_TRANSITION (transition));
431
remove_complete = !!remove_complete;
433
if (transition->priv->remove_on_complete == remove_complete)
436
transition->priv->remove_on_complete = remove_complete;
438
g_object_notify_by_pspec (G_OBJECT (transition),
439
obj_props[PROP_REMOVE_ON_COMPLETE]);
443
* clutter_transition_get_remove_on_complete:
444
* @transition: a #ClutterTransition
446
* Retrieves the value of the #ClutterTransition:remove-on-complete property.
448
* Return value: %TRUE if the @transition should be detached when complete,
449
* and %FALSE otherwise
454
clutter_transition_get_remove_on_complete (ClutterTransition *transition)
456
g_return_val_if_fail (CLUTTER_IS_TRANSITION (transition), FALSE);
458
return transition->priv->remove_on_complete;