This file is indexed.

/usr/share/gtk-doc/html/clutter-cookbook/animations-reuse.html is in libclutter-1.0-doc 1.20.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>6. Reusing a complex animation on different actors</title><link rel="stylesheet" type="text/css" href="style.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="The Clutter Cookbook"><link rel="up" href="animations.html" title="Chapter 5. Animations"><link rel="prev" href="animations-complex.html" title="5. Creating complex animations with ClutterAnimator"><link rel="next" href="animations-moving.html" title="7. Moving actors"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6. Reusing a complex animation on different actors</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="animations-complex.html">Prev</a> </td><th width="60%" align="center">Chapter 5. Animations</th><td width="20%" align="right"> <a accesskey="n" href="animations-moving.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="animations-reuse"></a>6. Reusing a complex animation on different actors</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="animations-reuse-problem"></a>6.1. Problem</h3></div></div></div><p>You want to apply the same complex animation to several
      different actors.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="animations-reuse-solution"></a>6.2. Solution</h3></div></div></div><p>Instead of animating each actor separately, create a
      <span class="emphasis"><em>rig</em></span>: an empty container with an associated
      animation, which will be animated in lieu of
      animating the actor directly. Do this as follows:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>Initialise the stage and actors, including those
          to be animated.</p></li><li class="listitem"><p>Define a <span class="type">ClutterContainer</span> and a
          <span class="type">ClutterAnimator</span> animation to animate it.</p></li><li class="listitem"><p>When you need to animate an actor:</p><div class="orderedlist"><ol class="orderedlist" type="a"><li class="listitem"><p>Create an instance of the rig and its animator.</p></li><li class="listitem"><p>Reparent the actor to the rig.</p></li><li class="listitem"><p>Run the rig's animation.</p></li></ol></div></li></ol></div><p>For this solution, we're using
      <a class="ulink" href="http://json.org/" target="_top">JSON</a> to define the
      animation and the user interface elements. For more
      details about this approach, see
      <a class="link" href="script.html#script-introduction" title="1. Introduction">the chapter
      on <span class="type">ClutterScript</span></a>.</p><p>Here's an extract of the JSON definition for the stage and
      one of five rectangles placed at its left edge (the full definition
      is in <a class="link" href="animations-reuse.html#animations-reuse-example-1" title="Example 5.5. ClutterScript JSON defining several rectangles with signal handlers">the
      appendix</a>):</p><div class="informalexample"><pre class="programlisting">[
  {
    "type" : "ClutterStage",
    "id" : "stage",

    ... stage properties, signal handlers etc. ...

    "children" : [
      {
        "type" : "ClutterRectangle",
        "id" : "rect1",
        "color" : "white",
        "width" : 50,
        "height" : 50,
        "y" : 50,
        "reactive" : true,
        "signals" : [
          { "name" : "button-press-event", "handler" : "foo_button_pressed_cb" }
        ]
      },

      ... more children defined here ...
    ]
  }
]</pre></div><p>The key point to note is how a signal handler is defined
      for the <code class="code">button-press-event</code>, so that the
      <code class="function">foo_button_pressed_cb()</code> function will trigger
      the animation when a (mouse) button is pressed on each rectangle.</p><p>The second JSON definition includes the rig
      (an empty <span class="type">ClutterGroup</span>) and a
      <span class="type">ClutterAnimator</span> to animate it. The animation moves the
      container across the stage and scales it to twice its original
      size. (This is the <a class="link" href="animations-reuse.html#animations-reuse-example-2" title='Example 5.6. ClutterScript JSON describing a "rig" and a ClutterAnimator animation'>same
      code as in the appendix</a>):</p><div class="informalexample"><pre class="programlisting">[
  {
    "type" : "ClutterGroup",
    "id" : "rig"
  },

  {
    "type" : "ClutterAnimator",
    "id" : "animator",
    "duration" : 2000,

    "properties" : [
      {
        "object" : "rig",
        "name" : "x",
        "ease-in" : true,
        "keys" : [
          [ 0.0, "linear", 0.0 ],
          [ 1.0, "easeOutCubic", 150.0 ]
        ]
      },
      {
        "object" : "rig",
        "name" : "scale-x",
        "ease-in" : true,
        "keys" : [
          [ 0.5, "linear", 1.0 ],
          [ 1.0, "easeOutBack", 2.0 ]
        ]
      },
      {
        "object" : "rig",
        "name" : "scale-y",
        "ease-in" : true,
        "keys" : [
          [ 0.5, "linear", 1.0 ],
          [ 1.0, "easeOutBack", 2.0 ]
        ]
      }
    ]
  }
]
</pre></div><p>The remaining parts of the application code load
      the user interface definition, setting up the stage and rectangles;
      and define the callback. The full code is
      <a class="link" href="animations-reuse.html#animations-reuse-example-3" title="Example 5.7. Loading ClutterScript from JSON files in response to events in a user interface">in the appendix</a>,
      but below is the most important part, the callback function:</p><div class="informalexample"><pre class="programlisting">gboolean
foo_button_pressed_cb (ClutterActor *actor,
                       ClutterEvent *event,
                       gpointer      user_data)
{
  ClutterScript *ui = CLUTTER_SCRIPT (user_data);
  ClutterStage *stage = CLUTTER_STAGE (clutter_script_get_object (ui, "stage"));

  ClutterScript *script;
  ClutterActor *rig;
  ClutterAnimator *animator;

  /* load the rig and its animator from a JSON file */
  script = clutter_script_new ();

  /* use a function defined statically in this source file to load the JSON */
  load_script_from_file (script, ANIMATION_FILE);

  clutter_script_get_objects (script,
                              "rig", &amp;rig,
                              "animator", &amp;animator,
                              NULL);

  /* remove the button press handler from the rectangle */
  g_signal_handlers_disconnect_by_func (actor,
                                        G_CALLBACK (foo_button_pressed_cb),
                                        NULL);

  /* add a callback to clean up the script when the rig is destroyed */
  g_object_set_data_full (G_OBJECT (rig), "script", script, g_object_unref);

  /* add the rig to the stage */
  clutter_actor_add_child (stage, rig);

  /* place the rig at the same coordinates on the stage as the rectangle */
  clutter_actor_set_position (rig,
                              clutter_actor_get_x (actor),
                              clutter_actor_get_y (actor));

  /* put the rectangle into the top-left corner of the rig */
  g_object_ref (actor);
  clutter_actor_remove_child (clutter_actor_get_parent (actor), actor);
  clutter_actor_add_child (rig, actor);

  clutter_actor_set_position (actor, 0, 0);

  /* animate the rig */
  clutter_animator_start (animator);

  return TRUE;
}</pre></div><p>The code creates a new rig and associated animation
      at the point when the rectangle is clicked. It then positions the
      rig at the same coordinates as the rectangle, reparents
      the rectangle to the rig, and starts the rig's animation.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The signal handler has to be declared non-static and
        you must use <code class="code">-export-dynamic</code> as an option to the
        compiler, otherwise the function isn't visible to
        <span class="type">ClutterScript</span> (as outlined
        <a class="link" href="script-signals.html" title="3. Connecting to signals in ClutterScript">in this recipe</a>).</p></div><p>This is what the animation looks like:</p><p><video controls="controls" src="videos/animations-reuse.ogv"><a href="videos/animations-reuse.ogv"></a></video></p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="animations-reuse-discussion"></a>6.3. Discussion</h3></div></div></div><p>The above solution reparents an actor to be animated
      into a rig (an empty placeholder). The rig is a container
      which acts as a temporary parent for the actor we
      <span class="emphasis"><em>really</em></span> want to animate. By animating the rig,
      it appears as though the actor inside it is being animated (but
      <a class="link" href="animations-reuse.html#animations-reuse-discussion-rig-not-actor" title="6.3.2. Caveats about animating a rig instead of an actor">see
      these caveats</a>). This means the same animation can be
      easily applied to different actors: create an
      instance of the rig, reparent an actor to it, then
      run the rig's animation. This is simpler than creating
      a separate animation for each actor individually, or
      reusing a single <span class="type">ClutterAnimator</span> on different
      actors (see
      <a class="link" href="animations-reuse.html#animations-reuse-discussion-one-or-many" title="6.3.1. One animation vs. many">this
      section</a>).</p><p>Using JSON enhances the animation's reusability (it's even
      potentially reusable in another application), makes the code
      simpler (an animation can be loaded directly from the script),
      and makes refactoring easier (the animation can be modified
      without recompiling the application code). However, it also puts
      some minor limitations on the animation's reusability; namely, you
      can only set absolute property values in a JSON animation
      definition. This makes JSON less useful in cases where
      you need to animate properties relative to their starting
      values: for example, "move 50 pixels along the x axis" or
      "rotate by 10 degrees more on the z axis". (This type of animation
      is probably less portable anyway.) In such cases, the programmable
      API may be a better option: see the <span class="type">ClutterAnimator</span>
      documentation for examples.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="animations-reuse-discussion-one-or-many"></a>6.3.1. One animation vs. many</h4></div></div></div><p>In the sample code, a new instance of the rig and its
        animation are created for each actor. One side effect of this
        is that all of the actors can animate simultaneously with the
        "same" animation. If you don't want this behaviour, but still
        want to use a rig approach, you could create a single instance
        of the rig and its animation. Then, you could reparent each actor
        to it in turn.</p><p>To ensure that the rig only animates one actor (or group
        of actors) at a time, you could track whether the rig is
        currently animating (e.g. by examining the animation's
        timeline with <code class="function">clutter_animator_get_timeline()</code>).
        Then, if the animation is running, prevent any other actor
        from being reparented to the rig.</p><p>Note that you would also need to "reset" the rig each time the
        animation completed (move it back to the right start values for
        its properties), ready to animate the next actor.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="animations-reuse-discussion-rig-not-actor"></a>6.3.2. Caveats about animating a rig instead of an actor</h4></div></div></div><p>There are a few issues to be aware of in cases
        where you animate a rig with contained actors, rather than
        animating the actor directly:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>Animating a rig doesn't <span class="emphasis"><em>always</em></span>
            produce the same visual effect as animating an actor directly.
            For example, compare the following cases:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>You rotate an actor by 180 degrees in the
                <code class="code">y</code> axis, then by 90 degrees in the
                <code class="code">z</code> axis. The actor appears to rotate in
                a <span class="emphasis"><em>clockwise</em></span> direction.</p></li><li class="listitem"><p>You rotate the parent container of an actor
                by 180 degrees in the <code class="code">y</code> axis; then rotate
                the actor by 90 degrees in the <code class="code">z</code> axis.
                The actor appears to rotate in an
                <span class="emphasis"><em>anti-clockwise</em></span> direction. By
                rotating the container, the "back" of the
                actor faces the view point, so the actor's movement
                appears reversed. See
                <a class="link" href="animations-rotating.html#animations-rotating-discussion-direction" title="4.3.2. Direction of rotation">this
                recipe</a> for more details.</p></li></ul></div><p>There may be other situations where you get similar
            discrepancies.</p></li><li class="listitem"><p>Animating a rig doesn't change an actor's properties,
            but animating the actor does.</p><p>When you animate a container rather than the actor
            directly, the reported properties of the actor may not
            reflect its visual appearance. For example, if you apply
            a scale animation to a container, the final scale of
            actors inside it (as returned by
            <code class="function">clutter_actor_get_scale()</code>) will not
            reflect the scaling applied to their container; whereas
            directly animating the actors would cause their scale
            properties to change.</p></li><li class="listitem"><p>Reparenting an actor to a rig can cause the actor
            to "jump" to the rig's position, unless you align the
            actor to the rig first.</p><p>Note that in the sample code, the position of the actor
            (<code class="code">x</code>, <code class="code">y</code> coordinates) is copied to
            the rig before the reparenting happens. The actor is then
            reparented to the rig, and positioned in the rig's
            top-left corner. So the actor appears to be in the same
            position, but is now actually inside a rig at the actor's old
            position.</p><p>Why bother to do this? Because the rig has a default
            position of <code class="code">0,0</code> (top-left of <span class="emphasis"><em>its</em></span>
            container, the stage). If you reparent the actor to the rig,
            without first copying the actor's position to the rig, the
            actor appears to "jump" to the rig's position.</p></li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="animations-reuse-examples"></a>6.4. Full example</h3></div></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The three separate code examples in this section
        constitute a single application which implements the above
        solution.</p></div><div class="example"><a name="animations-reuse-example-1"></a><p class="title"><b>Example 5.5. <span class="type">ClutterScript</span> JSON defining several
        rectangles with signal handlers</b></p><div class="example-contents"><pre class="programlisting">[
  {
    "type" : "ClutterStage",
    "id" : "stage",
    "width" : 300,
    "height" : 200,
    "color" : "#333355ff",

    "signals" : [
      { "name" : "destroy", "handler" : "clutter_main_quit" }
    ],

    "children" : [
      {
        "type" : "ClutterRectangle",
        "id" : "rect1",
        "color" : "white",
        "width" : 50,
        "height" : 50,
        "y" : 50,
        "reactive" : true,
        "signals" : [
          { "name" : "button-press-event", "handler" : "foo_button_pressed_cb" }
        ]
      },

      {
        "type" : "ClutterRectangle",
        "id" : "rect2",
        "color" : "blue",
        "width" : 50,
        "height" : 50,
        "y" : 50,
        "reactive" : true,
        "signals" : [
          { "name" : "button-press-event", "handler" : "foo_button_pressed_cb" }
        ]
      },

      {
        "type" : "ClutterRectangle",
        "id" : "rect3",
        "color" : "green",
        "width" : 50,
        "height" : 50,
        "y" : 50,
        "reactive" : true,
        "signals" : [
          { "name" : "button-press-event", "handler" : "foo_button_pressed_cb" }
        ]
      },

      {
        "type" : "ClutterRectangle",
        "id" : "rect4",
        "color" : "red",
        "width" : 50,
        "height" : 50,
        "y" : 50,
        "reactive" : true,
        "signals" : [
          { "name" : "button-press-event", "handler" : "foo_button_pressed_cb" }
        ]
      },

      {
        "type" : "ClutterRectangle",
        "id" : "rect5",
        "color" : "grey",
        "width" : 50,
        "height" : 50,
        "y" : 50,
        "reactive" : true,
        "signals" : [
          { "name" : "button-press-event", "handler" : "foo_button_pressed_cb" }
        ]
      }
    ]
  }
]
</pre></div></div><br class="example-break"><div class="example"><a name="animations-reuse-example-2"></a><p class="title"><b>Example 5.6. <span class="type">ClutterScript</span> JSON describing a "rig"
        and a <span class="type">ClutterAnimator</span> animation</b></p><div class="example-contents"><pre class="programlisting">[
  {
    "type" : "ClutterGroup",
    "id" : "rig"
  },

  {
    "type" : "ClutterAnimator",
    "id" : "animator",
    "duration" : 2000,

    "properties" : [
      {
        "object" : "rig",
        "name" : "x",
        "ease-in" : true,
        "keys" : [
          [ 0.0, "linear", 0.0 ],
          [ 1.0, "easeOutCubic", 150.0 ]
        ]
      },
      {
        "object" : "rig",
        "name" : "scale-x",
        "ease-in" : true,
        "keys" : [
          [ 0.5, "linear", 1.0 ],
          [ 1.0, "easeOutBack", 2.0 ]
        ]
      },
      {
        "object" : "rig",
        "name" : "scale-y",
        "ease-in" : true,
        "keys" : [
          [ 0.5, "linear", 1.0 ],
          [ 1.0, "easeOutBack", 2.0 ]
        ]
      }
    ]
  }
]
</pre></div></div><br class="example-break"><div class="example"><a name="animations-reuse-example-3"></a><p class="title"><b>Example 5.7. Loading <span class="type">ClutterScript</span> from JSON files
        in response to events in a user interface</b></p><div class="example-contents"><pre class="programlisting">#include &lt;stdlib.h&gt;
#include &lt;clutter/clutter.h&gt;

#define UI_FILE "animations-reuse-ui.json"
#define ANIMATION_FILE "animations-reuse-animation.json"

static gboolean
load_script_from_file (ClutterScript *script,
                       gchar         *filename)
{
  GError *error = NULL;

  clutter_script_load_from_file (script, filename, &amp;error);

  if (error != NULL)
    {
      g_critical ("Error loading ClutterScript file %s\n%s", filename, error-&gt;message);
      g_error_free (error);
      exit (EXIT_FAILURE);
    }

  return TRUE;
}

gboolean
foo_button_pressed_cb (ClutterActor *actor,
                       ClutterEvent *event,
                       gpointer      user_data)
{
  ClutterScript *ui = CLUTTER_SCRIPT (user_data);
  ClutterStage *stage = CLUTTER_STAGE (clutter_script_get_object (ui, "stage"));

  ClutterScript *script;
  ClutterActor *rig;
  ClutterAnimator *animator;

  /* load the rig and its animator from a JSON file */
  script = clutter_script_new ();

  /* use a function defined statically in this source file to load the JSON */
  load_script_from_file (script, ANIMATION_FILE);

  clutter_script_get_objects (script,
                              "rig", &amp;rig,
                              "animator", &amp;animator,
                              NULL);

  /* remove the button press handler from the rectangle */
  g_signal_handlers_disconnect_by_func (actor,
                                        G_CALLBACK (foo_button_pressed_cb),
                                        NULL);

  /* add a callback to clean up the script when the rig is destroyed */
  g_object_set_data_full (G_OBJECT (rig), "script", script, g_object_unref);

  /* add the rig to the stage */
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), rig);

  /* place the rig at the same coordinates on the stage as the rectangle */
  clutter_actor_set_position (rig,
                              clutter_actor_get_x (actor),
                              clutter_actor_get_y (actor));

  /* put the rectangle into the top-left corner of the rig */
  clutter_actor_reparent (actor, rig);

  clutter_actor_set_position (actor, 0, 0);

  /* animate the rig */
  clutter_animator_start (animator);

  return TRUE;
}

int
main (int argc, char *argv[])
{
  ClutterScript *script;
  ClutterActor *stage;

  if (clutter_init (&amp;argc, &amp;argv) != CLUTTER_INIT_SUCCESS)
    return 1;

  script = clutter_script_new ();
  load_script_from_file (script, UI_FILE);

  clutter_script_connect_signals (script, script);

  clutter_script_get_objects (script,
                              "stage", &amp;stage,
                              NULL);

  clutter_actor_show (stage);

  clutter_main ();

  g_object_unref (script);

  return EXIT_SUCCESS;
}
</pre></div></div><br class="example-break"></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="animations-complex.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="animations.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="animations-moving.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Creating complex animations with
    <span class="type">ClutterAnimator</span> </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 7. Moving actors</td></tr></table></div></body></html>