mirror of
https://github.com/brl/mutter.git
synced 2024-11-30 03:50:47 -05:00
3c2defee9d
* clutter/clutter-container.[ch]: Add a generic actor container interface, for actors to implement without subclassing ClutterGroup. * clutter/clutter-group.[ch]: Make ClutterGroup implement the ClutterContainer interface, and deprecate the colliding methods. * clutter/clutter-layout.[ch]: Add extended layout interface. Actors and containers requiring or honouring complex layout management should implement this interface and provide at least one of the available layout types: width for height, height for width, natural size, iterative size request. * clutter/clutter-label.c: A ClutterLabel requires height for width layout management, so it implements the ClutterLayout interface. * clutter/Makefile.am: Add new files to the build. * tests/*.c: * examples/*.c: Update tests and examples code to use the new ClutterContainer API instead of ClutterGroup.
197 lines
4.3 KiB
C
197 lines
4.3 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include <clutter/clutter.h>
|
|
|
|
typedef struct Tile
|
|
{
|
|
ClutterActor *actor;
|
|
gint orig_pos;
|
|
}
|
|
Tile;
|
|
|
|
static Tile *Tiles[4][4];
|
|
static int TileW, TileH, BlankTileX, BlankTileY;
|
|
static ClutterEffectTemplate *Template;
|
|
static ClutterTimeline *EffectTimeline;
|
|
|
|
ClutterActor*
|
|
make_tiles (GdkPixbuf *pixbuf)
|
|
{
|
|
int x, y , w, h;
|
|
int i = 0, j = 0;
|
|
int pos = 0;
|
|
ClutterActor *group;
|
|
|
|
group = clutter_group_new();
|
|
|
|
w = gdk_pixbuf_get_width (pixbuf);
|
|
h = gdk_pixbuf_get_height (pixbuf);
|
|
|
|
TileW = w / 4;
|
|
TileH = h / 4;
|
|
|
|
for (y = 0; y < h; y += TileH)
|
|
{
|
|
for (x = 0; x < w; x += TileW)
|
|
{
|
|
GdkPixbuf *subpixbuf;
|
|
Tile *tile;
|
|
|
|
subpixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
|
|
8, TileW, TileH);
|
|
|
|
gdk_pixbuf_copy_area (pixbuf, x, y, TileW, TileH,
|
|
subpixbuf, 0, 0);
|
|
|
|
tile = g_slice_new0 (Tile);
|
|
|
|
if (pos != 15)
|
|
{
|
|
tile->actor = clutter_texture_new_from_pixbuf (subpixbuf);
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (group),
|
|
tile->actor);
|
|
clutter_actor_set_position (tile->actor, x, y);
|
|
}
|
|
else
|
|
{
|
|
/* blank tile */
|
|
tile->actor = NULL;
|
|
BlankTileX = i;
|
|
BlankTileY = j;
|
|
}
|
|
|
|
g_object_unref (subpixbuf);
|
|
|
|
tile->orig_pos = pos;
|
|
Tiles[j][i] = tile;
|
|
|
|
pos++; i++;
|
|
}
|
|
i=0; j++;
|
|
}
|
|
|
|
return group;
|
|
}
|
|
|
|
static void
|
|
switch_blank_tile (int i, int j)
|
|
{
|
|
Tile *tmp;
|
|
ClutterKnot knots[2];
|
|
|
|
knots[0].x = i * TileW;
|
|
knots[0].y = j * TileH;
|
|
|
|
knots[1].x = BlankTileX * TileW;
|
|
knots[1].y = BlankTileY * TileH;
|
|
|
|
EffectTimeline = clutter_effect_move (Template,
|
|
Tiles[j][i]->actor,
|
|
knots,
|
|
2,
|
|
NULL,
|
|
NULL);
|
|
|
|
/* Add a week pointer to returned timeline so we know whilst its
|
|
* playing and thus valid.
|
|
*/
|
|
g_object_add_weak_pointer (G_OBJECT(EffectTimeline),
|
|
(gpointer*)&EffectTimeline);
|
|
|
|
tmp = Tiles[BlankTileY][BlankTileX];
|
|
Tiles[BlankTileY][BlankTileX] = Tiles[j][i];
|
|
Tiles[j][i] = tmp;
|
|
|
|
BlankTileY = j;
|
|
BlankTileX = i;
|
|
}
|
|
|
|
static void
|
|
key_press_event_cb (ClutterStage *stage,
|
|
ClutterKeyEvent *event,
|
|
gpointer user_data)
|
|
{
|
|
Tile *tmp, *tmp2;
|
|
|
|
if (clutter_key_event_symbol(event) == CLUTTER_q)
|
|
clutter_main_quit();
|
|
|
|
/* Do move if there is a move already happening */
|
|
if (EffectTimeline != NULL)
|
|
return;
|
|
|
|
switch (clutter_key_event_symbol(event))
|
|
{
|
|
case CLUTTER_Up:
|
|
if (BlankTileY < 3)
|
|
switch_blank_tile (BlankTileX, BlankTileY+1);
|
|
break;
|
|
case CLUTTER_Down:
|
|
if (BlankTileY > 0)
|
|
switch_blank_tile (BlankTileX, BlankTileY-1);
|
|
break;
|
|
case CLUTTER_Left:
|
|
if (BlankTileX < 3)
|
|
switch_blank_tile (BlankTileX+1, BlankTileY);
|
|
break;
|
|
case CLUTTER_Right:
|
|
if (BlankTileX > 0)
|
|
switch_blank_tile (BlankTileX-1, BlankTileY);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
GError *error;
|
|
GdkPixbuf *pixbuf;
|
|
ClutterActor *stage, *group;
|
|
ClutterColor bgcolour;
|
|
|
|
/* Initiate clutter */
|
|
clutter_init (&argc, &argv);
|
|
|
|
/* Setup the stage */
|
|
stage = clutter_stage_get_default ();
|
|
g_object_set (stage, "fullscreen", TRUE, NULL);
|
|
|
|
clutter_color_parse ("#000000", &bgcolour);
|
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &bgcolour);
|
|
|
|
/* Create Tiles */
|
|
error = NULL;
|
|
pixbuf = gdk_pixbuf_new_from_file ("image.jpg", &error);
|
|
if (error)
|
|
{
|
|
g_warning ("Unable to load `image.jpg': %s", error->message);
|
|
g_error_free (error);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
group = make_tiles (pixbuf);
|
|
|
|
/* Add to stage and center */
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
|
|
clutter_actor_set_position (group,
|
|
(clutter_actor_get_width (stage) - clutter_actor_get_width (group)) / 2,
|
|
(clutter_actor_get_height (stage) - clutter_actor_get_height (group)) / 2);
|
|
|
|
/* Link up event collection */
|
|
g_signal_connect (stage,
|
|
"key-press-event",
|
|
G_CALLBACK(key_press_event_cb),
|
|
NULL);
|
|
|
|
/* Template to use for slider animation */
|
|
Template = clutter_effect_template_new (clutter_timeline_new (15, 60),
|
|
CLUTTER_ALPHA_RAMP_INC);
|
|
|
|
clutter_actor_show_all (stage);
|
|
|
|
clutter_main();
|
|
}
|