1 /*
2 * Clutter.
3 *
4 * An OpenGL based 'interactive canvas' library.
5 *
6 * Copyright (C) 2009 Intel Corporation.
7 *
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.
12 *
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.
17 *
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/>.
20 *
21 * Author:
22 * Emmanuele Bassi <ebassi@linux.intel.com>
23 */
24
25 /**
26 * SECTION:clutter-animatable
27 * @short_description: Interface for animatable classes
28 *
29 * #ClutterAnimatable is an interface that allows a #GObject class
30 * to control how a #ClutterAnimation will animate a property.
31 *
32 * Each #ClutterAnimatable should implement the
33 * #ClutterAnimatableIface.interpolate_property() virtual function of the
34 * interface to compute the animation state between two values of an interval
35 * depending on a progress factor, expressed as a floating point value.
36 *
37 * If a #ClutterAnimatable is animated by a #ClutterAnimation
38 * instance, the #ClutterAnimation will call
39 * clutter_animatable_interpolate_property() passing the name of the
40 * currently animated property; the values interval; and the progress factor.
41 * The #ClutterAnimatable implementation should return the computed value for
42 * the animated
43 * property.
44 *
45 * #ClutterAnimatable is available since Clutter 1.0
46 */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #define CLUTTER_DISABLE_DEPRECATION_WARNINGS
53
54 #include "clutter-animatable.h"
55 #include "clutter-interval.h"
56 #include "clutter-debug.h"
57 #include "clutter-private.h"
58
59 #include "deprecated/clutter-animatable.h"
60 #include "deprecated/clutter-animation.h"
61
62 typedef ClutterAnimatableIface ClutterAnimatableInterface;
63 G_DEFINE_INTERFACE (ClutterAnimatable, clutter_animatable, G_TYPE_OBJECT);
64
65 static void
clutter_animatable_default_init(ClutterAnimatableInterface * iface)66 clutter_animatable_default_init (ClutterAnimatableInterface *iface)
67 {
68 }
69
70 /**
71 * clutter_animatable_animate_property:
72 * @animatable: a #ClutterAnimatable
73 * @animation: a #ClutterAnimation
74 * @property_name: the name of the animated property
75 * @initial_value: the initial value of the animation interval
76 * @final_value: the final value of the animation interval
77 * @progress: the progress factor
78 * @value: return location for the animation value
79 *
80 * Calls the animate_property() virtual function for @animatable.
81 *
82 * The @initial_value and @final_value #GValue<!-- -->s must contain
83 * the same type; @value must have been initialized to the same
84 * type of @initial_value and @final_value.
85 *
86 * All implementation of the #ClutterAnimatable interface must
87 * implement this function.
88 *
89 * Return value: %TRUE if the value has been validated and can
90 * be applied to the #ClutterAnimatable, and %FALSE otherwise
91 *
92 * Since: 1.0
93 *
94 * Deprecated: 1.8: Use clutter_animatable_interpolate_value()
95 * instead
96 */
97 gboolean
clutter_animatable_animate_property(ClutterAnimatable * animatable,ClutterAnimation * animation,const gchar * property_name,const GValue * initial_value,const GValue * final_value,gdouble progress,GValue * value)98 clutter_animatable_animate_property (ClutterAnimatable *animatable,
99 ClutterAnimation *animation,
100 const gchar *property_name,
101 const GValue *initial_value,
102 const GValue *final_value,
103 gdouble progress,
104 GValue *value)
105 {
106 ClutterAnimatableIface *iface;
107 gboolean res;
108
109 g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), FALSE);
110 g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), FALSE);
111 g_return_val_if_fail (property_name != NULL, FALSE);
112 g_return_val_if_fail (initial_value != NULL && final_value != NULL, FALSE);
113 g_return_val_if_fail (G_VALUE_TYPE (initial_value) != G_TYPE_INVALID, FALSE);
114 g_return_val_if_fail (G_VALUE_TYPE (final_value) != G_TYPE_INVALID, FALSE);
115 g_return_val_if_fail (value != NULL, FALSE);
116 g_return_val_if_fail (G_VALUE_TYPE (value) == G_VALUE_TYPE (initial_value) &&
117 G_VALUE_TYPE (value) == G_VALUE_TYPE (final_value),
118 FALSE);
119
120 iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
121 if (iface->animate_property == NULL)
122 {
123 ClutterInterval *interval;
124
125 interval = clutter_animation_get_interval (animation, property_name);
126 if (interval == NULL)
127 return FALSE;
128
129 res = clutter_animatable_interpolate_value (animatable, property_name,
130 interval,
131 progress,
132 value);
133 }
134 else
135 res = iface->animate_property (animatable, animation,
136 property_name,
137 initial_value, final_value,
138 progress,
139 value);
140
141 return res;
142 }
143
144 /**
145 * clutter_animatable_find_property:
146 * @animatable: a #ClutterAnimatable
147 * @property_name: the name of the animatable property to find
148 *
149 * Finds the #GParamSpec for @property_name
150 *
151 * Return value: (transfer none): The #GParamSpec for the given property
152 * or %NULL
153 *
154 * Since: 1.4
155 */
156 GParamSpec *
clutter_animatable_find_property(ClutterAnimatable * animatable,const gchar * property_name)157 clutter_animatable_find_property (ClutterAnimatable *animatable,
158 const gchar *property_name)
159 {
160 ClutterAnimatableIface *iface;
161
162 g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL);
163 g_return_val_if_fail (property_name != NULL, NULL);
164
165 CLUTTER_NOTE (ANIMATION, "Looking for property '%s'", property_name);
166
167 iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
168 if (iface->find_property != NULL)
169 return iface->find_property (animatable, property_name);
170
171 return g_object_class_find_property (G_OBJECT_GET_CLASS (animatable),
172 property_name);
173 }
174
175 /**
176 * clutter_animatable_get_initial_state:
177 * @animatable: a #ClutterAnimatable
178 * @property_name: the name of the animatable property to retrieve
179 * @value: a #GValue initialized to the type of the property to retrieve
180 *
181 * Retrieves the current state of @property_name and sets @value with it
182 *
183 * Since: 1.4
184 */
185 void
clutter_animatable_get_initial_state(ClutterAnimatable * animatable,const gchar * property_name,GValue * value)186 clutter_animatable_get_initial_state (ClutterAnimatable *animatable,
187 const gchar *property_name,
188 GValue *value)
189 {
190 ClutterAnimatableIface *iface;
191
192 g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable));
193 g_return_if_fail (property_name != NULL);
194
195 CLUTTER_NOTE (ANIMATION, "Getting initial state of '%s'", property_name);
196
197 iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
198 if (iface->get_initial_state != NULL)
199 iface->get_initial_state (animatable, property_name, value);
200 else
201 g_object_get_property (G_OBJECT (animatable), property_name, value);
202 }
203
204 /**
205 * clutter_animatable_set_final_state:
206 * @animatable: a #ClutterAnimatable
207 * @property_name: the name of the animatable property to set
208 * @value: the value of the animatable property to set
209 *
210 * Sets the current state of @property_name to @value
211 *
212 * Since: 1.4
213 */
214 void
clutter_animatable_set_final_state(ClutterAnimatable * animatable,const gchar * property_name,const GValue * value)215 clutter_animatable_set_final_state (ClutterAnimatable *animatable,
216 const gchar *property_name,
217 const GValue *value)
218 {
219 ClutterAnimatableIface *iface;
220
221 g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable));
222 g_return_if_fail (property_name != NULL);
223
224 CLUTTER_NOTE (ANIMATION, "Setting state of property '%s'", property_name);
225
226 iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
227 if (iface->set_final_state != NULL)
228 iface->set_final_state (animatable, property_name, value);
229 else
230 g_object_set_property (G_OBJECT (animatable), property_name, value);
231 }
232
233 /**
234 * clutter_animatable_interpolate_value:
235 * @animatable: a #ClutterAnimatable
236 * @property_name: the name of the property to interpolate
237 * @interval: a #ClutterInterval with the animation range
238 * @progress: the progress to use to interpolate between the
239 * initial and final values of the @interval
240 * @value: (out): return location for an initialized #GValue
241 * using the same type of the @interval
242 *
243 * Asks a #ClutterAnimatable implementation to interpolate a
244 * a named property between the initial and final values of
245 * a #ClutterInterval, using @progress as the interpolation
246 * value, and store the result inside @value.
247 *
248 * This function should be used for every property animation
249 * involving #ClutterAnimatable<!-- -->s.
250 *
251 * This function replaces clutter_animatable_animate_property().
252 *
253 * Return value: %TRUE if the interpolation was successful,
254 * and %FALSE otherwise
255 *
256 * Since: 1.8
257 */
258 gboolean
clutter_animatable_interpolate_value(ClutterAnimatable * animatable,const gchar * property_name,ClutterInterval * interval,gdouble progress,GValue * value)259 clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
260 const gchar *property_name,
261 ClutterInterval *interval,
262 gdouble progress,
263 GValue *value)
264 {
265 ClutterAnimatableIface *iface;
266
267 g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), FALSE);
268 g_return_val_if_fail (property_name != NULL, FALSE);
269 g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), FALSE);
270 g_return_val_if_fail (value != NULL, FALSE);
271
272 CLUTTER_NOTE (ANIMATION, "Interpolating '%s' (progress: %.3f)",
273 property_name,
274 progress);
275
276 iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
277 if (iface->interpolate_value != NULL)
278 {
279 return iface->interpolate_value (animatable, property_name,
280 interval,
281 progress,
282 value);
283 }
284 else
285 return clutter_interval_compute_value (interval, progress, value);
286 }
287