Clutter 综述
作者: Matthew Allum
日期: 2008-10-28
本文是Matthew Allum 在 GUADEC 2007 上做的报告,对 Clutter 进行了详细、全面的介绍,给出了一些例子代码,并对 Clutter 的将来做了展望。

What is Clutter

  • 一个 toolkit/scenegraph/canvas 库,使用 OpenGL/OpenGL ES 渲染
  • 依赖于 GOject, Glib, GDKPixbuf 和 Pango;
  • 目的是创建速度快、支持动画效果、视觉丰富的图形界面;
  • 原始 (raw) 但是灵活 (flexible) 的 API
  • 不是一个通用的 OpenGL 接口,是一个带有 3D 效果的 2D (2D with 3D effects).
  • 基于 C 开发,基于 LGPL 发布

Why clutter

  • 让使用者摆脱了 OpenGL API 和相关数学知识带来的复杂性;
  • 简洁的 面向对象的类似 GTK+ 的 API,并提供了窗口和事件抽象;
  • 3D 桌面硬件和 3D 嵌入式硬件越来越流行;

Where to use Clutter

  • Media boxes,如 Microsoft Media Center, Apple's Front Row;
  • 桌面应用特效,如 iTunes 的 Coverflow, 图片浏览器的 slideshow;
  • 嵌入式设备:Zune, iPhone 等

Internals

  • All fixed point math (fixed and float API entry points);
  • ClutterUnits
  • Timeline Pool
  • Custome Pango render - efficient text rendering

Backends

  • Clutter backend essentially abstracted into 2 parts:
  • 'Cogl' layer abstracts over regular GL and GL ES;
  • Features allows easy runtime detection of missing features (eg YUV textures, texture reads).

Bindings

  • Perl, Python, Mono

General concepts

  • Actors (Widgets): 可视界面元素;
  • Stage (Window):actors 加入到 Stage 中;
  • Actors 可以有父亲元素,也可以有孩子元素;
  • 通过事件和动画直接操作 actors.

Actors

  • All Actors can be tranformed in various ways:
    • Position ed in 3D space (via pixels or ClutterUnits);
    • Rotated around 3 Axis;
    • Sized;
    • Scaled;
    • Have Opacity set;
    • Clipped;
  • Transforms also apply to children;
  • Position relative to parent;

A simple Actor example

#include <clutter/clutter.h>

int main (int argc, char* argv[])
{
    ClutterActor *stage, *actor;
    GdkPixbuf * pixbuf;

    clutter_init (&argc, &argv);
    stage = clutter_stage_get_default ();
    pixbuf = gdk_pixbuf_new_from_file ("superoh,png", NULL);
    actor = clutter_texture_new_from_pixbuf (pixbuf);

    clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
    clutter_actor_set_position (actor, 100, 100);
    clutter_actor_rotate_z (actor, 180.0,
                            clutter_actor_get_width (actor)/2,
                            cluter_actor_get_height (actor)/2);

    clutter_actor_show_all (stage);
    clutter_main ();

    return 0;
}

Simple Actor Example II

    pixbuf = gdk_pixbuf_new_from_file ("redhand,png", NULL);
    group = clutter_group_new ();

    actor1 = clutter_texture_new_from_pixbuf (pixbuf);
    actor2 = clutter_texture_new_from_pixbuf (pixbuf);

    clutter_container_add (CLUTTER_CONTAINER (group), actor1, actor2,
                           NULL);
    clutter_actor_set_position (actor1, 0, 0);
    clutter_actor_set_position (actor2, 200, 0);

    clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
    clutter_actor_set_position (group, 100, 100);
    clutter_actor_rotate_z (group, 45.0,
                            clutter_actor_get_width (group)/2,
                            cluter_actor_get_height (group)/2);

    clutter_actor_show_all (group);
    clutter_actor_show_all (stage);

    clutter_main ();

Included Actors

  • ClutterTexture, ClutterAnimationTexture, ClutterCloneTexture
  • ClutterRectangle
  • ClutterLabel
  • ClutterEntry
  • ClutterContainer, ClutterStage, ClutterGroup, ClutterVBox, ClutterHBox
  • ClutterCairo, ClutterGstVideo (Via Add ons)
  • Easy to subclass and make your own

Events

  • Simple processed input events (keyboard, mouse)
  • All signals from stage
  • clutter_stage_actor_at_pos ()
  • Reasoning: performance, focus model;
  • Plans to improve RSN;

ClutterTimelines

  • 动画的基础;
  • 指定总帧数和每秒钟对应的帧;
  • Callback on a new frame
  • Skips 'dropped' frames
  • Delay, Stop, start, pause, loop

Timeline Example:

void on_new_frame (ClutterTimeline* timeline, gint frame_num,
        gpointer data)
{
    ClutterActor *actor = CLUTTER_ACTOR (data);
    clutter_actor_rotate_z (actor, (gdouble)frame_num,
                            clutter_actor_get_width (actor)/2,
                            cluter_actor_get_height (actor)/2);
}

int main (int argc, char* argv[])
{
    ClutterTimeline* timeline;
    ...
    timeline = clutter_timeline_new (360, 60); /*num frames, fps*/
    g_object_set (timeline, "loop", TRUE, NULL); /* have it loop */

    /* fire a callback for frame change */
    g_signal_connect (timeline, "new-frame",
                      G_CALLBACK (on_new_frame), actor);

    clutter_timeline_start (timeline);
    ...
}

ClutterAlphas

  • A function of time - not pixel alpha;
  • Takes a timeline as parameter and a function;
  • Produces a value between 0 and CLUTTER_ALPHA_MAX;
  • Various prebuilt functions included: ramps, sinewaves, smoothstep, exponential, etc
  • In a word, A clutterAlpha binds a Timeline to a progress function which translates the time T into an adimensional factor alpha. The factor can then be used to drive a Behaviour, which translates the value into something meaningful for an Actor.

ClutterBehaviours

  • Manipultates actors properties in various ways driven by Alphas;
  • Makes complex animations easy.
  • Opacity, Rotation, Depth. Paths, BSplines Paths, Ellipse Paths;
  • Mix, Stack, Easy to roll your own.

Behaviour example

    timeline = clutter_timeline_new (100, 26); /* num frames, fps */

    /**/
    alpha = clutter_alpha_new_full (timeline, CLUTTER_ALPHA_SINE,
                                    NULL, NULL);
    behave = clutter_behaviour_ellipse_new (alpha,
                                            200, /* center x */
                                            200, /* center y */
                                            400, /* width */
                                            300, /* height */
                                            0.0, /* angle begin */
                                            360.0, /* angle end */
                                            0.0  /* title */ );
    clutter_behaviour_apply (behave, actor);

    /* start the timeline and thus the animations */
    clutter_timeline_start (timeline);

ClutterEffects

  • 'One shot' effects
  • Utility wrapper around timelines+alphas+behaviours
  • More limited, but easy
    ClutterEffectTemplate* template;
    effect_template = clutter_effect_template_new(
                                  clutter_time_line_new (60, 60),
                                  CLUTTER_ALPHA_RAMP_INC);
    clutter_effect_scale (effect_template, actor, 1.0, 4.0,
                          CLUTTER_GRAVITY_CENTER,
                          on_completion_callback,
                          on_completion_callback_data);

ClutterCairo

  • A cairo Canvas Actor, 2 API calls
  • not accelerated (yet)
    actor = clutter_cairo_new (width, height);
    cr = clutter_cairo_create (CLUTTER_CAIRO(actor));
    ... cairo rendering calls...
    cairo_destroy (cr);

ClutterGst

  • Video Texture Actor - simple video file playback
  • Clutter Texture Sink - for custom pipelines
  • Simpel audio playback also

ClutterGTK

  • GTK Clutter Canvas widget
  • Allows clutter to be embedded into GTK apps

SeeAlso

http://www.clutter-project.org/presentations/clutter-foo/slide-01.html