1. 概述
2. 准备环境
3. 基本 Actor
stage
基本 Clutter 程序设计 和 stage 的基本概念
stage widget
Actors
示例:两个静止的 actor
Tansformations (转换)
Containers (容器)
一个完整实例

1. 概述

Clutter 是一个 C API 集合。核心概念是: stage (画布,舞台)和 actor (演员)。画布相当于一个 window ,或者 framebuffer ,是 actor 的舞台。 所有的 Clutter 程序都需要创建一个 stage ,它是最顶层的对象,也是一个 container (容器,让其他 actor 在上面表演)。 actor 们本身都是 2D 对 象,是平面的,不过 Clutter 允许我们对这些 actor 在 3D 空间进行操作, 比如绕着 x,y,z 轴旋转。

Clutter 除了可以让我们在 3D 空间操作 2D 的 actor 外,最有特色的就是可 以使用时间线,通过多条时间线的协同使用,我们可以很容易创造出“有生气”“有 活力”的程序。

当然, Clutter 也会处理传统的键盘、鼠标事件!

这就是 Clutter !

2. 准备环境

以下实例都以 libclutter-0.9-dev 为基础

要使用 clutter APIs ,可以使用下面命令得到的参数编译程序:

pkg-config clutter-0.9 --cflags
pkg-config clutter-0.9 --libs

如果使用 automake,authconf 之类工具,可以设置 PKG_CHECK_MODULES 宏:

PKG_CHECK_MODULES(EXAMPLE, clutter-0.9)
AC_SUBST(EXAMPLE_CFLAGS)
AC_SUBST(EXAMPLE_LIBS)

3. 基本 Actor

先看一个例子,修改 moblin 网站的 sample-helloworld 程序,使之可以显示 UTF-8 字符集。源程序: clutter_春江花月夜

这个例子中的五个字会随机运动,绕着x,y,z轴随机旋转。编译源代码:

gcc -Wall `pkg-config clutter-0.9 --cflags --libs` clutter_春江花月夜.c
./a.out

stage

每个 Clutter 应用程序都至少包括一个 ClutterStage 。这个 stage 容纳 Actors (比如 rectangles,images,or text).

基本 Clutter 程序设计 和 stage 的基本概念

clutter_init()
clutter_stage_get_default()
clutter_actor_show()
clutter_container_add()
clutter_main()

开始一个 clutter 程序,使用 clutter_init() 初始化。使用 clutter_stage_get_default() 创建一个 stage 。也可以使用 GtkClutterEmbed widget 在一个 GTK+ 窗口中使用 Clutter。

ClutterStage 从 ClutterActor 对象派生,所以很多 ClutterActor 的属性都可以 用在 stage 上。例如调用 clutter_actor_show() 显示stage。

ClutterStage 也操作 ClutterContainer ,允许使用 clutter_container_add() 添加子 actors。

调用 clutter_main() 开始一个 main loop,让 stage “活”起来!

#include <clutter/clutter.h>
#include <stdlib.h>

static gboolean
on_stage_button_press (ClutterStage *stage,ClutterEvent *event,gpointer data)
{
  gint x = 0;
  gint y = 0;
  clutter_event_get_coords (event,&x,&y);
  g_print ("在 (%d,%d) 处点击 : ",x,y);
  if (x < 250)
    printf("stage左边部分!\n");
  else if (x == 250)
    printf("中奖了!恰好是中间!\n");
  else
    printf("stage右边部分!\n");
  return TRUE;
}

int main(int argc,char **argv)
{
  ClutterColor stage_color = {0x00,0x00,0x00,0xff};

  clutter_init (&argc,&argv);

  // 创建 stage 并设置大小和颜色
  ClutterActor *stage = clutter_stage_get_default();
  clutter_actor_set_size(stage,500,200);
  clutter_stage_set_color(CLUTTER_STAGE(stage),&stage_color);

  // 显示 stage
  clutter_actor_show(stage);

  // 连接事件
  g_signal_connect (stage,"button-press-event",
                    G_CALLBACK(on_stage_button_press),NULL);

  // 让 stage 活起来
  clutter_main();

  return EXIT_SUCCESS;
}

stage widget

GtkClutterEmbed widget 允许把 ClutterStage 放到一个 GTK+ 窗口中。使用 gtk_clutter_embed_new() 创建一个实例,再用 gtk_clutter_embed_get_stage() 从 GtkClutterEmbed 对象创建一个 ClutterStage 实例.

使用 GtkClutterEmbed widget ,需要用 gtk_clutter_init 代替 clutter_init 和 gtk_init 初始化 Clutter 和 GTK+。使用 gtk_main() 代替 clutter_main() 创建 main loop。

#include <gtk/gtk.h>
#include <clutter/clutter.h>
#include <clutter-gtk/clutter-gtk.h>
#include <stdlib.h>

int main (int argc, char **argv)
{
  ClutterColor stage_color = {0x61,0x64,0x8c,0xff};

  if (gtk_clutter_init (&argc,&argv) != CLUTTER_INIT_SUCCESS)
    g_error ("初始化 GtkClutter 失败!");

  if (argc !=2)
    g_error ("用法: 程序名 <image file>");

  // 创建一个 toplevel 窗口
  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_default_size (GTK_WINDOW (window),640,480);
  gtk_window_set_title (GTK_WINDOW (window),"浏览图片");
  g_signal_connect (window,"destory",
                    G_CALLBACK(gtk_main_quit),NULL);

  // 创建一个 table 包括 scrollbar 和 clutter embed widget
  GtkWidget *table = gtk_table_new (2,2,FALSE);
  gtk_container_add (GTK_CONTAINER (window),table);
  gtk_widget_show (table);

  // 创建一个 ClutterEmbed widget
  GtkWidget *embed = gtk_clutter_embed_new();
  gtk_table_attach (GTK_TABLE (table),embed,
                    0,1,
                    0,1,
                    GTK_EXPAND | GTK_FILL,
                    GTK_EXPAND | GTK_FILL,
                    0,0);
  gtk_widget_show (embed);

  // 初始化 stage
  ClutterActor *stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (embed));
  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
  clutter_actor_set_size (stage,640,480);

  // 创建一个 viewport actor
  ClutterActor *viewport = gtk_clutter_viewport_new (NULL,NULL);
  clutter_container_add_actor (CLUTTER_CONTAINER (stage),viewport);

  // 加载 image
  ClutterActor *texture = clutter_texture_new_from_file (argv[1],NULL);
  clutter_container_add_actor (CLUTTER_CONTAINER (viewport),texture);
  clutter_actor_set_position (texture,0,0);
  clutter_actor_set_position (viewport,0,0);
  clutter_actor_set_size (viewport,640,480);

  // 创建 scrollbar ,并连接到 viewport
  GtkAdjustment *h_adjustment = NULL;
  GtkAdjustment *v_adjustment = NULL;
  gtk_clutter_scrollable_get_adjustments (GTK_CLUTTER_SCROLLABLE (viewport),
                                          &h_adjustment,&v_adjustment);
  GtkWidget *scrollbar = gtk_vscrollbar_new (v_adjustment);
  gtk_table_attach (GTK_TABLE (table),scrollbar,
                    1,2,
                    0,1,
                    0,GTK_EXPAND | GTK_FILL,
                    0,0);
  gtk_widget_show (scrollbar);

  scrollbar = gtk_hscrollbar_new (h_adjustment);
  gtk_table_attach (GTK_TABLE (table),scrollbar,
                    0,1,
                    1,2,
                    GTK_EXPAND | GTK_FILL,0,
                    0,0);

  gtk_widget_show (scrollbar);
  gtk_widget_show (window);

  gtk_main();

  return EXIT_SUCCESS;
}

Actors

Clutter 中基本 actor 有:

每个 actor 需要用 clutter_container_add() 添加到 stage 中,并且用 clutter_actor_set_position() 设置位置(x,y坐标),z 轴使用 clutter_actor_set_depth() 设置。使用 clutter_actor_set_size() 设置宽度和 长度(width and height)

actor 的位置默认在 parent container(比如stage) 的 top-left(0,0),可以用 clutter_actor_set_anchor_point() 改变。

默认情况下,actor 是隐藏的,需要调用 clutter_actor_show() 显示。可以调用 clutter_actor_hide() 隐藏对象。

actor 可以使用 scaling (缩放) 、rotation (旋转) 、partly transparent (透 明) 变形。

示例:两个静止的 actor

#include <clutter/clutter.h>
#include <stdlib.h>

int main (int argc, char **argv)
{
  ClutterColor stage_color = {0x00,0x00,0x00,0xff};
  ClutterColor actor_color = {0xff,0xff,0xff,0x99};

  clutter_init (&argc, &argv);

  // 创建 stage 并设置大小和颜色
  ClutterActor *stage = clutter_stage_get_default ();
  clutter_actor_set_size (stage,300,200);
  clutter_stage_set_color (CLUTTER_STAGE (stage),&stage_color);

  // 添加一个 rectangle 到 stage
  ClutterActor *rect = clutter_rectangle_new_with_color (&actor_color);
  clutter_actor_set_size (rect,150,100);
  clutter_actor_set_position (rect,20,20);
  clutter_container_add_actor (CLUTTER_CONTAINER (stage),rect);
  clutter_actor_show (rect);

  // 添加一个 label 到 stage
  ClutterActor *label = clutter_text_new_full ("Sans 12","测试文本",&actor_color);
  clutter_actor_set_size (label,500,500);
  clutter_actor_set_position (label,20,160);
  clutter_container_add_actor (CLUTTER_CONTAINER (stage),label);
  clutter_actor_show (label);

  // 显示 stage
  clutter_actor_show (stage);

  clutter_main();

  return EXIT_SUCCESS;
}

Tansformations (转换)

Actors can be scaled, rotated, and moved.

Scaling (缩放比例)

调用 clutter_actor_set_scale() 增加和减少actor显示的大小。但是不改变 clutter_actor_get_width()clutter_actor_get_height() 的值。因为它仅仅 改变用户"看到"的大小。再次调用 clutter_actor_set_scale() 会替换第一次的改变 而不是在之基础上。

Rotation (旋转,循环)

调用 clutter_actor_set_rotation() 可以让 actor 绕着坐标轴(axis)旋转,坐标 轴可以是 CLUTTER_X_AXIS、CLUTTER_Y_AXIS、CLUTTER_Z_AXIS 或想要的角度。

同 clutter_actor_set_scale() 一样,这个函数也不改变 actor 本身的值,比如 用 clutter_actor_get_x() 的到的值。

Clipping (剪切)

actor 可以用 clutter_actor_set_clip() 剪切后只让部分可见。这样,可以创建 一个很大的 actor,然后设置一个 clip rectangle,这样任何时刻只有一部分可见。 可以使用 clutter_actor_remove_clip() 删除。

Movement

可以使用 clutter_actor_move_by()clutter_actor_set_depth() 移动 actor。

clutter_actor_move_by() 会改变 clutter_actor_get_x() 的值!

示例

#include <clutter/clutter.h>
#include <stdlib.h>

int main (int argc, char **argv)
{
  ClutterColor stage_color = {0x00,0x00,0x00,0xff};
  ClutterColor actor_color = {0xff,0xff,0xff,0x99};

  clutter_init (&argc, &argv);

  ClutterActor *stage = clutter_stage_get_default ();
  clutter_actor_set_size (stage,500,300);
  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);

  ClutterActor *rect = clutter_rectangle_new_with_color (&actor_color);
  clutter_actor_set_size (rect,150,150);
  clutter_actor_set_position (rect,20,20);
  clutter_container_add_actor (CLUTTER_CONTAINER (stage),rect);
  clutter_actor_show (rect);

  clutter_actor_set_rotation (rect,CLUTTER_X_AXIS,-80,0,0,0);

  ClutterActor *label = clutter_text_new_full ("Sans 12","春江花月夜",&actor_color);
  clutter_actor_set_size (label,500,500);
  clutter_actor_set_position (label,60,150);
  clutter_container_add_actor (CLUTTER_CONTAINER (stage),label);
  clutter_actor_show (label);

  clutter_actor_set_scale (label,6.00,1.0);

  clutter_actor_move_by (label,20,-20);

  clutter_actor_set_depth (label,-80);

  clutter_actor_show (stage);
  clutter_main();

  return EXIT_SUCCESS;
}

Containers (容器)

ClutterContainer
ClutterStage
ClutterGroup

使用 ClutterGroup 可以同时操作几个 actor

示例:两个actor组成的ClutterGroup

#include <clutter/clutter.h>
#include <stdlib.h>

int main (int argc, char **argv)
{
  ClutterColor stage_color = {0x00,0x00,0x00,0xff};
  ClutterColor actor_color = {0xff,0xff,0xff,0x99};

  clutter_init (&argc, &argv);

  // 创建 stage 并设置大小和颜色
  ClutterActor *stage = clutter_stage_get_default ();
  clutter_actor_set_size (stage,300,200);
  clutter_stage_set_color (CLUTTER_STAGE (stage),&stage_color);

  // 添加一个 group
  ClutterActor *group = clutter_group_new ();
  clutter_actor_set_position (group,40,40);
  clutter_container_add_actor (CLUTTER_CONTAINER (stage),group);
  clutter_actor_show (group);

  // 添加一个 rectangle 到 group
  ClutterActor *rect = clutter_rectangle_new_with_color (&actor_color);
  clutter_actor_set_size (rect,50,50);
  clutter_actor_set_position (rect,0,0);
  clutter_container_add_actor (CLUTTER_CONTAINER (group),rect);
  clutter_actor_show (rect);

  // 添加一个 label 到 group
  ClutterActor *label = clutter_text_new_full ("Sans 9","春江潮水连海平",&actor_color);
  clutter_actor_set_position (label,0,60);
  clutter_container_add_actor (CLUTTER_CONTAINER (group),label);
  clutter_actor_show (label);

  // 绕 x 轴 scale group 到 120%
  clutter_actor_set_scale (group,3.00,1.0);

  // 绕 z 周 ratate
  clutter_actor_set_rotation (group,CLUTTER_Z_AXIS,10,0,0,0);

  clutter_actor_show (stage);
  clutter_main ();

  return EXIT_SUCCESS;
}

一个完整实例