[gnome-games] gnometris: First pass as implementing a GObject-based texture cache; has issues
- From: Jason Clinton <jclinton src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-games] gnometris: First pass as implementing a GObject-based texture cache; has issues
- Date: Wed, 26 Aug 2009 03:42:47 +0000 (UTC)
commit 459603c43a158b98f1912e0a8e508fcd5703e979
Author: Jason D. Clinton <me jasonclinton com>
Date: Tue Aug 25 22:36:50 2009 -0500
gnometris: First pass as implementing a GObject-based texture cache; has issues
gnometris/Makefile.am | 4 +-
gnometris/blockops.cpp | 127 ++++------------
gnometris/blockops.h | 39 +----
gnometris/blocks-cache.cpp | 327 ++++++++++++++++++++++++++++++++++++++++
gnometris/blocks-cache.h | 65 ++++++++
gnometris/blocks.cpp | 72 +++++++++
gnometris/blocks.h | 35 +++++
gnometris/preview.cpp | 37 ++----
gnometris/preview.h | 8 +-
gnometris/renderer.cpp | 83 ++---------
gnometris/renderer.h | 25 +---
gnometris/tetris.cpp | 4 +-
gnometris/tetris.h | 2 +-
libgames-support/games-debug.c | 1 +
libgames-support/games-debug.h | 7 +-
15 files changed, 574 insertions(+), 262 deletions(-)
---
diff --git a/gnometris/Makefile.am b/gnometris/Makefile.am
index d2154c2..7823885 100644
--- a/gnometris/Makefile.am
+++ b/gnometris/Makefile.am
@@ -21,7 +21,9 @@ gnometris_SOURCES = \
blockops.cpp \
blockops.h \
renderer.cpp \
- renderer.h
+ renderer.h \
+ blocks-cache.cpp \
+ blocks-cache.h
gnometris_CPPFLAGS = \
-I$(top_srcdir) \
diff --git a/gnometris/blockops.cpp b/gnometris/blockops.cpp
index 385bfdc..a5d24b1 100644
--- a/gnometris/blockops.cpp
+++ b/gnometris/blockops.cpp
@@ -22,89 +22,14 @@
*/
#include <config.h>
+
#include "blockops.h"
-#include "blocks.h"
+#include <cairo/cairo.h>
#include <clutter-gtk/clutter-gtk.h>
+#include "tetris.h"
#define FONT "Sans Bold"
-Block::Block ():
- what(EMPTY),
- actor(NULL),
- x(0),
- y(0),
- move_behaviour(NULL),
- fall_behaviour(NULL),
- explode_move_behaviour(NULL)
-{}
-
-Block::~Block ()
-{
- if (actor)
- clutter_actor_destroy (CLUTTER_ACTOR(actor));
- if (move_behaviour)
- g_object_unref (move_behaviour);
- if (fall_behaviour)
- g_object_unref (fall_behaviour);
- if (explode_move_behaviour)
- g_object_unref (explode_move_behaviour);
-}
-
-void
-Block::createActor (ClutterActor *chamber, cairo_surface_t *texture_source)
-{
- if (actor)
- clutter_actor_destroy (CLUTTER_ACTOR(actor));
- actor = clutter_texture_new ();
- // FIXME jclinton ... this should really be cluttercairo somehow for efficiency
- clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE(actor),
- cairo_image_surface_get_data(texture_source),
- TRUE,
- cairo_image_surface_get_width(texture_source),
- cairo_image_surface_get_height(texture_source),
- cairo_image_surface_get_stride(texture_source),
- 32, CLUTTER_TEXTURE_NONE, NULL);
- clutter_group_add (CLUTTER_GROUP (chamber), actor);
- clutter_actor_set_position (CLUTTER_ACTOR(actor), x, y);
- clutter_actor_show (CLUTTER_ACTOR(actor));
-}
-
-void
-Block::bindAnimations (BlockOps *f)
-{
- move_behaviour = clutter_behaviour_path_new_with_knots (f->move_alpha,
- NULL, 0);
-
- fall_behaviour = clutter_behaviour_path_new_with_knots (f->fall_alpha,
- NULL, 0);
-
- explode_move_behaviour = clutter_behaviour_path_new_with_knots (f->explode_alpha,
- NULL, 0);
-}
-
-Block&
-Block::moveFrom (Block& b, BlockOps *f)
-{
- if (this != &b) {
- what = b.what;
- b.what = EMPTY;
- color = b.color;
- b.color = 0;
- if (b.actor) {
- const ClutterKnot knot_line[] = {{b.x, b.y}, {x, y}};
- fall_behaviour = clutter_behaviour_path_new_with_knots (f->fall_alpha,
- knot_line, 2);
- clutter_behaviour_apply (fall_behaviour, b.actor);
- f->fall_behaviours = g_list_prepend (f->fall_behaviours, fall_behaviour);
- }
- actor = b.actor;
- b.actor = NULL;
- }
- return *this;
-}
-
-/******************************************************************************/
-
gboolean
BlockOps::move_end (ClutterTimeline *time, BlockOps *f)
{
@@ -156,7 +81,7 @@ BlockOps::BlockOps() :
height(0),
cell_width(0),
cell_height(0),
- renderer(NULL),
+ cache(NULL),
themeID(-1),
blocknr(0),
rot(0),
@@ -178,7 +103,7 @@ BlockOps::BlockOps() :
stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (w));
playingField = clutter_group_new ();
- clutter_group_add (CLUTTER_GROUP(stage), CLUTTER_ACTOR(playingField));
+ clutter_stage_add (stage, playingField);
move_time = clutter_timeline_new (60);
g_signal_connect (move_time, "completed", G_CALLBACK
@@ -635,9 +560,13 @@ BlockOps::emptyField(int filled_lines, int fill_prob)
guint tmpColor = g_random_int_range(0, NCOLOURS);
field[x][y].what = LAYING;
field[x][y].color = tmpColor;
- field[x][y].createActor (playingField, renderer->getCacheCellById (tmpColor));
+ field[x][y].createActor (playingField,
+ blocks_cache_get_block_texture_by_id (cache,
+ tmpColor),
+ cell_width,
+ cell_height);
clutter_actor_set_position (CLUTTER_ACTOR(field[x][y].actor),
- x*(cell_width), y*(cell_height));
+ x*(cell_width), y*(cell_height));
}
}
}
@@ -662,7 +591,10 @@ BlockOps::putBlockInField (SlotType fill)
field[i][j].color = color;
if (fill == FALLING) {
field[i][j].createActor (playingField,
- renderer->getCacheCellById (color));
+ blocks_cache_get_block_texture_by_id (cache,
+ color),
+ cell_width,
+ cell_height);
} else {
if (field[i][j].actor) {
clutter_actor_destroy (field[i][j].actor);
@@ -735,6 +667,7 @@ BlockOps::resize(GtkWidget *widget, GtkAllocation *allocation, BlockOps *field)
{
field->width = allocation->width;
field->height = allocation->height;
+
if (field->width == 0 || field->height == 0)
return FALSE;
field->cell_width = field->width/COLUMNS;
@@ -769,11 +702,12 @@ BlockOps::rescaleField ()
cairo_t *bg_cr;
- if (renderer)
- renderer->rescaleCache (cell_width, cell_height);
+ /*if (cache)
+ g_object_unref (cache);
else {
- renderer = rendererFactory (themeID, cell_width, cell_height);
- }
+ cache = blocks_cache_new ();
+ blocks_cache_set_theme (cache, themeID);
+ }*/
if (background) {
clutter_actor_set_size (CLUTTER_ACTOR(background), width, height);
@@ -786,8 +720,9 @@ BlockOps::rescaleField ()
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
clutter_stage_set_color (CLUTTER_STAGE (stage),
&stage_color);
- clutter_group_add (CLUTTER_GROUP (stage),
+ clutter_stage_add (stage,
background);
+ clutter_actor_set_position (CLUTTER_ACTOR (background), 0, 0);
}
rescaleBlockPos ();
@@ -799,8 +734,9 @@ BlockOps::rescaleField ()
width, height);
} else {
foreground = clutter_cairo_texture_new (width, height);
- clutter_group_add (CLUTTER_GROUP (stage),
+ clutter_stage_add (stage,
foreground);
+ clutter_actor_set_position (CLUTTER_ACTOR (foreground), 0, 0);
}
bg_cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE(background));
@@ -837,8 +773,6 @@ BlockOps::rescaleField ()
center_anchor_x, center_anchor_y);
clutter_actor_raise (CLUTTER_ACTOR (playingField),
CLUTTER_ACTOR(background));
-
- clutter_actor_show_all (stage);
}
void
@@ -852,7 +786,6 @@ BlockOps::drawMessage()
char *msg;
cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE(foreground));
- clutter_actor_raise_top (CLUTTER_ACTOR(foreground));
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
@@ -957,13 +890,11 @@ BlockOps::setTheme (gint id)
return;
themeID = id;
- if (renderer) {
- delete renderer;
- renderer = rendererFactory (themeID, cell_width,
- cell_height);
+ if (cache) {
+ blocks_cache_set_theme (cache, themeID);
} else {
- renderer = rendererFactory (themeID, cell_width,
- cell_height);
+ cache = blocks_cache_new ();
+ blocks_cache_set_theme (cache, themeID);
}
rescaleBlockPos();
}
diff --git a/gnometris/blockops.h b/gnometris/blockops.h
index 54ea06c..3ce265c 100644
--- a/gnometris/blockops.h
+++ b/gnometris/blockops.h
@@ -22,39 +22,12 @@
* For more details see the file COPYING.
*/
-#include "tetris.h"
-#include "renderer.h"
-#include <clutter/clutter.h>
-
-enum SlotType {
- EMPTY,
- FALLING,
- LAYING
-};
-
-class Block {
-public:
- Block ();
- ~Block ();
-
- Block& moveFrom (Block &b, BlockOps *f);
+#include "blocks.h"
+#include "blocks-cache.h"
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtk.h>
- SlotType what;
- guint color;
- ClutterActor *actor;
-
- int x;
- int y;
-
- void createActor (ClutterActor *chamber, cairo_surface_t *texture_source);
- void bindAnimations (BlockOps *f);
-
- /* Every block will have a unique position
- * These can be continuously cleared and repopulated with new paths */
- ClutterBehaviour *move_behaviour;
- ClutterBehaviour *fall_behaviour;
- ClutterBehaviour *explode_move_behaviour;
-};
+//typedef struct _BlocksCache BlocksCache;
class BlockOps {
friend class Block;
@@ -131,7 +104,7 @@ private:
guint height;
guint cell_width;
guint cell_height;
- Renderer *renderer;
+ BlocksCache *cache;
gint themeID;
Block **field;
diff --git a/gnometris/blocks-cache.cpp b/gnometris/blocks-cache.cpp
new file mode 100644
index 0000000..98c0144
--- /dev/null
+++ b/gnometris/blocks-cache.cpp
@@ -0,0 +1,327 @@
+/*
+ Copyright © 2008 Neil Roberts
+ Copyright © 2008 Christian Persch
+ Copyright © 2009 Jason D. Clinton
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <glib-object.h>
+#include <cairo.h>
+#include <cogl/cogl.h>
+
+#include "blocks.h"
+#include "renderer.h"
+#include "blocks-cache.h"
+
+#include "../libgames-support/games-debug.h"
+
+struct _BlocksCachePrivate
+{
+ guint theme;
+ //guint theme_changed_handler;
+
+ CoglHandle *colours;
+
+#ifdef GNOME_ENABLE_DEBUG
+ guint n_calls;
+ guint cache_hits;
+#endif
+};
+
+enum
+{
+ PROP_0,
+ PROP_THEME
+};
+
+/* This is an invalid value for a CoglHandle, and distinct from COGL_INVALID_HANDLE */
+#define FAILED_HANDLE ((gpointer) 0x1)
+#define IS_FAILED_HANDLE(ptr) (G_UNLIKELY ((ptr) == FAILED_HANDLE))
+
+/* Logging */
+#ifdef GNOME_ENABLE_DEBUG
+#define LOG_CALL(obj) obj->priv->n_calls++
+#define LOG_CACHE_HIT(obj) obj->priv->cache_hits++
+#define LOG_CACHE_MISS(obj)
+#else
+#define LOG_CALL(obj)
+#define LOG_CACHE_HIT(obj)
+#define LOG_CACHE_MISS(obj)
+#endif /* GNOME_ENABLE_DEBUG */
+
+static void blocks_cache_dispose (GObject *object);
+static void blocks_cache_finalize (GObject *object);
+
+G_DEFINE_TYPE (BlocksCache, blocks_cache, G_TYPE_OBJECT);
+
+#define BLOCKS_CACHE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_BLOCKS_CACHE, BlocksCachePrivate))
+
+/* Helper functions */
+
+static void
+blocks_cache_clear (BlocksCache *cache)
+{
+ BlocksCachePrivate *priv = cache->priv;
+ int i;
+
+ _games_debug_print (GAMES_DEBUG_BLOCKS_CACHE,
+ "blocks_cache_clear\n");
+
+ for (i = 0; i < NCOLOURS; i++) {
+ CoglHandle handle = priv->colours[i];
+
+ if (handle != COGL_INVALID_HANDLE &&
+ !IS_FAILED_HANDLE (handle)) {
+ cogl_texture_unref (handle);
+ }
+
+ priv->colours[i] = COGL_INVALID_HANDLE;
+ }
+}
+
+static void
+blocks_cache_unset_theme (BlocksCache *cache)
+{
+ BlocksCachePrivate *priv = cache->priv;
+
+ //g_signal_handler_disconnect (GUINT_TO_POINTER(priv->theme), priv->theme_changed_handler);
+ priv->theme = NULL;
+ //priv->theme_changed_handler = 0;
+}
+
+/* Class implementation */
+
+static void
+blocks_cache_init (BlocksCache *self)
+{
+ BlocksCachePrivate *priv;
+
+ priv = self->priv = BLOCKS_CACHE_GET_PRIVATE (self);
+
+ priv->colours = static_cast<void**>(g_malloc0 (sizeof (CoglHandle) * NCOLOURS));
+}
+
+static void
+blocks_cache_dispose (GObject *object)
+{
+ BlocksCache *cache = BLOCKS_CACHE (object);
+
+ blocks_cache_clear (cache);
+ blocks_cache_unset_theme (cache);
+
+ G_OBJECT_CLASS (blocks_cache_parent_class)->dispose (object);
+}
+
+static void
+blocks_cache_finalize (GObject *object)
+{
+ BlocksCache *cache = BLOCKS_CACHE (object);
+ BlocksCachePrivate *priv = cache->priv;
+
+ g_free (priv->colours);
+
+#ifdef GNOME_ENABLE_DEBUG
+ _GAMES_DEBUG_IF (GAMES_DEBUG_BLOCKS_CACHE) {
+ _games_debug_print (GAMES_DEBUG_BLOCKS_CACHE,
+ "BlocksCache %p statistics: %u calls with %u hits and %u misses for a hit/total of %.3f\n",
+ cache, priv->n_calls, priv->cache_hits, priv->n_calls - priv->cache_hits,
+ priv->n_calls > 0 ? (double) priv->cache_hits / (double) priv->n_calls : 0.0);
+ }
+#endif
+
+ G_OBJECT_CLASS (blocks_cache_parent_class)->finalize (object);
+}
+
+static void
+blocks_cache_set_property (GObject *self,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ BlocksCache *cache = BLOCKS_CACHE (self);
+
+ switch (property_id) {
+ case PROP_THEME:
+ blocks_cache_set_theme (cache, g_value_get_uint (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec);
+ break;
+ }
+}
+
+static void
+blocks_cache_get_property (GObject *self,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ BlocksCache *cache = BLOCKS_CACHE (self);
+
+ switch (property_id) {
+ case PROP_THEME:
+ g_value_set_object (value, GUINT_TO_POINTER(blocks_cache_get_theme (cache)));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec);
+ break;
+ }
+}
+
+static void
+blocks_cache_class_init (BlocksCacheClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GParamSpec *pspec;
+
+ gobject_class->dispose = blocks_cache_dispose;
+ gobject_class->finalize = blocks_cache_finalize;
+ gobject_class->set_property = blocks_cache_set_property;
+ gobject_class->get_property = blocks_cache_get_property;
+
+ g_type_class_add_private (klass, sizeof (BlocksCachePrivate));
+
+ pspec = g_param_spec_uint ("theme", NULL, NULL,
+ 0, 2, 0,
+ static_cast<GParamFlags>(G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (gobject_class, PROP_THEME, pspec);
+}
+
+/* Public API */
+
+/**
+ * blocks_cache_new:
+ *
+ * Returns: a new #BlocksCache object
+ */
+BlocksCache *
+blocks_cache_new (void)
+{
+ return static_cast<BlocksCache*>(g_object_new (TYPE_BLOCKS_CACHE, NULL));
+}
+
+/**
+ * blocks_cache_set_theme:
+ * @cache:
+ * @theme:
+ *
+ * Sets the block theme.
+ */
+void
+blocks_cache_set_theme (BlocksCache *cache,
+ guint theme)
+{
+ BlocksCachePrivate *priv = cache->priv;
+
+ g_return_if_fail (IS_BLOCKS_CACHE (cache));
+
+ if (priv->theme == theme)
+ return;
+
+ blocks_cache_clear (cache);
+ blocks_cache_unset_theme (cache);
+
+ priv->theme = theme;
+ //priv->theme_changed_handler = g_signal_connect_swapped (GUINT_TO_POINTER(theme), "changed",
+ // G_CALLBACK (blocks_cache_clear),
+ // cache);
+ g_object_notify (G_OBJECT (cache), "theme");
+}
+
+/**
+ * blocks_cache_get_theme:
+ * @cache:
+ *
+ * Returns: the the block theme of @cache
+ */
+guint
+blocks_cache_get_theme (BlocksCache *cache)
+{
+ g_return_val_if_fail (IS_BLOCKS_CACHE (cache), NULL);
+
+ return cache->priv->theme;
+}
+
+/**
+ * blocks_cache_get_block_texture_by_id:
+ * @cache:
+ * @colour:
+ *
+ * Returns: a cached #CoglHandle for @colour.
+ */
+CoglHandle
+blocks_cache_get_block_texture_by_id (BlocksCache *cache,
+ guint colour)
+{
+ BlocksCachePrivate *priv = cache->priv;
+ CoglHandle handle;
+
+ g_return_val_if_fail (colour < NCOLOURS , NULL);
+
+ LOG_CALL (cache);
+
+ handle = priv->colours[colour];
+ if (IS_FAILED_HANDLE (handle)) {
+ LOG_CACHE_HIT (cache);
+ return COGL_INVALID_HANDLE;
+ }
+
+ if (handle == COGL_INVALID_HANDLE) {
+ cairo_surface_t *imgbuf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ 64, 64); /*FIXME for pixel-level precision*/
+
+ LOG_CACHE_MISS (cache);
+
+ Renderer *renderer = rendererFactory (priv->theme);
+ cairo_t *cr = cairo_create (imgbuf);
+
+ if (!cr) {
+ priv->colours[colour] = FAILED_HANDLE;
+ return COGL_INVALID_HANDLE;
+ }
+
+ renderer->drawCell (cr, colour);
+ cairo_destroy (cr);
+
+ handle = cogl_texture_new_from_data (64,
+ 64,
+ COGL_TEXTURE_NONE,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ COGL_PIXEL_FORMAT_ANY,
+ 2048,
+ cairo_image_surface_get_data (imgbuf));
+ cairo_surface_destroy (imgbuf);
+
+ if (handle == COGL_INVALID_HANDLE) {
+ priv->colours[colour] = FAILED_HANDLE;
+ return COGL_INVALID_HANDLE;
+ }
+
+ priv->colours[colour] = handle;
+ } else {
+ LOG_CACHE_HIT (cache);
+ }
+
+ return handle;
+}
+
diff --git a/gnometris/blocks-cache.h b/gnometris/blocks-cache.h
new file mode 100644
index 0000000..491213e
--- /dev/null
+++ b/gnometris/blocks-cache.h
@@ -0,0 +1,65 @@
+/*
+ Copyright © 2008 Neil Roberts
+ Copyright © 2008 Christian Persch
+ Copyright © 2009 Jason D. Clinton
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BLOCKS_CACHE_H
+#define BLOCKS_CACHE_H
+
+#include <glib-object.h>
+#include <cogl/cogl.h>
+
+G_BEGIN_DECLS
+
+#define TYPE_BLOCKS_CACHE (blocks_cache_get_type())
+#define BLOCKS_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BLOCKS_CACHE, BlocksCache))
+#define BLOCKS_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BLOCKS_CACHE, BlocksCacheClass))
+#define IS_BLOCKS_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BLOCKS_CACHE))
+#define IS_BLOCKS_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BLOCKS_CACHE))
+#define BLOCKS_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BLOCKS_CACHE, BlocksCacheClass))
+
+typedef struct _BlocksCache BlocksCache;
+typedef struct _BlocksCacheClass BlocksCacheClass;
+typedef struct _BlocksCachePrivate BlocksCachePrivate;
+
+struct _BlocksCacheClass
+{
+ GObjectClass parent_class;
+};
+
+struct _BlocksCache
+{
+ GObject parent;
+
+ BlocksCachePrivate *priv;
+};
+
+GType blocks_cache_get_type (void);
+
+BlocksCache *blocks_cache_new (void);
+
+void blocks_cache_set_theme (BlocksCache *cache,
+ guint theme);
+
+guint blocks_cache_get_theme (BlocksCache *cache);
+
+CoglHandle blocks_cache_get_block_texture_by_id (BlocksCache *cache,
+ guint colour);
+
+G_END_DECLS
+
+#endif /* BLOCKS_CACHE_H */
diff --git a/gnometris/blocks.cpp b/gnometris/blocks.cpp
index 123b365..f2afd23 100644
--- a/gnometris/blocks.cpp
+++ b/gnometris/blocks.cpp
@@ -19,6 +19,78 @@
* For more details see the file COPYING.
*/
+#include "blocks.h"
+#include "blockops.h"
+
+Block::Block ():
+ what(EMPTY),
+ actor(NULL),
+ x(0),
+ y(0),
+ move_behaviour(NULL),
+ fall_behaviour(NULL),
+ explode_move_behaviour(NULL)
+{}
+
+Block::~Block ()
+{
+ if (actor)
+ clutter_actor_destroy (CLUTTER_ACTOR(actor));
+ if (move_behaviour)
+ g_object_unref (move_behaviour);
+ if (fall_behaviour)
+ g_object_unref (fall_behaviour);
+ if (explode_move_behaviour)
+ g_object_unref (explode_move_behaviour);
+}
+
+void
+Block::createActor (ClutterActor *chamber, CoglHandle texture_source, gint pxwidth, gint pxheight)
+{
+ if (actor)
+ clutter_actor_destroy (CLUTTER_ACTOR(actor));
+ actor = clutter_texture_new ();
+ clutter_texture_set_cogl_texture (CLUTTER_TEXTURE(actor),
+ texture_source);
+ clutter_group_add (CLUTTER_GROUP (chamber), actor);
+ clutter_actor_set_position (CLUTTER_ACTOR(actor), x, y);
+ clutter_actor_show (CLUTTER_ACTOR(actor));
+}
+
+void
+Block::bindAnimations (BlockOps *f)
+{
+ move_behaviour = clutter_behaviour_path_new_with_knots (f->move_alpha,
+ NULL, 0);
+
+ fall_behaviour = clutter_behaviour_path_new_with_knots (f->fall_alpha,
+ NULL, 0);
+
+ explode_move_behaviour = clutter_behaviour_path_new_with_knots (f->explode_alpha,
+ NULL, 0);
+}
+
+Block&
+Block::moveFrom (Block& b, BlockOps *f)
+{
+ if (this != &b) {
+ what = b.what;
+ b.what = EMPTY;
+ color = b.color;
+ b.color = 0;
+ if (b.actor) {
+ const ClutterKnot knot_line[] = {{b.x, b.y}, {x, y}};
+ fall_behaviour = clutter_behaviour_path_new_with_knots (f->fall_alpha,
+ knot_line, 2);
+ clutter_behaviour_apply (fall_behaviour, b.actor);
+ f->fall_behaviours = g_list_prepend (f->fall_behaviours, fall_behaviour);
+ }
+ actor = b.actor;
+ b.actor = NULL;
+ }
+ return *this;
+}
+
int blockTable[][4][4][4] =
{
{
diff --git a/gnometris/blocks.h b/gnometris/blocks.h
index 8c154b6..7b84dab 100644
--- a/gnometris/blocks.h
+++ b/gnometris/blocks.h
@@ -22,8 +22,43 @@
* For more details see the file COPYING.
*/
+#include <clutter/clutter.h>
+#include <cogl/cogl.h>
+
+class BlockOps;
+
#define NCOLOURS 7
+enum SlotType {
+ EMPTY,
+ FALLING,
+ LAYING
+};
+
+class Block {
+public:
+ Block ();
+ ~Block ();
+
+ Block& moveFrom (Block &b, BlockOps *f);
+
+ SlotType what;
+ guint color;
+ ClutterActor *actor;
+
+ int x;
+ int y;
+
+ void createActor (ClutterActor *chamber, CoglHandle texture_source, gint pxwidth, gint pxheight);
+ void bindAnimations (BlockOps *f);
+
+ /* Every block will have a unique position
+ * These can be continuously cleared and repopulated with new paths */
+ ClutterBehaviour *move_behaviour;
+ ClutterBehaviour *fall_behaviour;
+ ClutterBehaviour *explode_move_behaviour;
+};
+
extern int blockTable[][4][4][4];
extern int tableSize;
diff --git a/gnometris/preview.cpp b/gnometris/preview.cpp
index 03f6c22..1d96f34 100644
--- a/gnometris/preview.cpp
+++ b/gnometris/preview.cpp
@@ -20,7 +20,6 @@
* For more details see the file COPYING.
*/
-#include <config.h>
#include "preview.h"
#define PREVIEW_WIDTH 6
@@ -35,7 +34,7 @@ Preview::Preview():
blocknr(-1),
color(-1),
themeID(-1),
- renderer(NULL),
+ cache(NULL),
enabled(true)
{
blocks = new Block*[PREVIEW_WIDTH];
@@ -61,7 +60,6 @@ Preview::Preview():
piece = clutter_group_new ();
clutter_group_add (CLUTTER_GROUP (stage),
piece);
- clutter_actor_show_all (stage);
piece_timeline = clutter_timeline_new (180);
alpha = clutter_alpha_new_full (piece_timeline,
@@ -79,7 +77,7 @@ Preview::~Preview ()
delete[] blocks[i];
delete[] blocks;
- delete renderer;
+ g_object_unref (cache);
}
void
@@ -91,27 +89,12 @@ Preview::enable(bool en)
void
Preview::setTheme (gint id)
{
- if (themeID == id)
- return;
-
themeID = id;
- if (renderer) {
- delete renderer;
- renderer = rendererFactory (themeID, PREVIEW_SIZE*4, PREVIEW_SIZE*4);
- } else {
- renderer = rendererFactory (themeID, PREVIEW_SIZE*4, PREVIEW_SIZE*4);
- }
-}
+ if (cache)
+ g_object_unref (cache);
+ cache = blocks_cache_new ();
-void
-Preview::regenerateRenderer ()
-{
- if (renderer)
- renderer->rescaleCache (PREVIEW_SIZE*4, PREVIEW_SIZE*4);
- else {
- renderer = rendererFactory (themeID, PREVIEW_SIZE*4, PREVIEW_SIZE*4);
- }
}
void
@@ -131,20 +114,21 @@ Preview::previewBlock(gint bnr, gint bcol)
blockTable[blocknr][0][x-1][y-1]) {
blocks[x][y].what = LAYING;
blocks[x][y].createActor (piece,
- renderer->getCacheCellById (color));
+ blocks_cache_get_block_texture_by_id (cache, color),
+ PREVIEW_SIZE*4,
+ PREVIEW_SIZE*4);
clutter_actor_set_position (CLUTTER_ACTOR(blocks[x][y].actor),
- x*PREVIEW_SIZE*4, y*PREVIEW_SIZE*4);
+ x*PREVIEW_SIZE*4, y*PREVIEW_SIZE*4);
} else {
blocks[x][y].what = EMPTY;
if (blocks[x][y].actor) {
- clutter_actor_destroy (blocks[x][y].actor);
+ clutter_actor_destroy (CLUTTER_ACTOR(blocks[x][y].actor));
blocks[x][y].actor = NULL;
}
}
}
}
clutter_timeline_start (piece_timeline);
- clutter_actor_show_all (stage);
}
gint
@@ -152,7 +136,6 @@ Preview::resize(GtkWidget *widget, GtkAllocation *allocation, Preview *preview)
{
preview->width = allocation->width;
preview->height = allocation->height;
- preview->regenerateRenderer ();
clutter_actor_set_anchor_point (preview->piece, PREVIEW_SIZE*10, PREVIEW_SIZE*10);
clutter_actor_set_position (CLUTTER_ACTOR(preview->piece), PREVIEW_SIZE*10, PREVIEW_SIZE*10);
preview->previewBlock (preview->blocknr, preview->color);
diff --git a/gnometris/preview.h b/gnometris/preview.h
index 60d16b9..8a66c6c 100644
--- a/gnometris/preview.h
+++ b/gnometris/preview.h
@@ -23,11 +23,8 @@
*/
#include "tetris.h"
-#include "blockops.h"
-#include "renderer.h"
#include "blocks.h"
-
-#include <clutter/clutter.h>
+#include "blocks-cache.h"
#include <clutter-gtk/clutter-gtk.h>
class Preview {
@@ -42,7 +39,6 @@ public:
void enable (bool enable);
void setTheme (gint id);
void previewBlock (int bnr, int bcolor);
- void regenerateRenderer ();
private:
GtkWidget *w;
@@ -58,7 +54,7 @@ private:
Block **blocks;
ClutterActor* piece;
- Renderer* renderer;
+ BlocksCache *cache;
bool enabled;
diff --git a/gnometris/renderer.cpp b/gnometris/renderer.cpp
index ccbc29c..3fe63ea 100644
--- a/gnometris/renderer.cpp
+++ b/gnometris/renderer.cpp
@@ -22,8 +22,8 @@
*/
#include <config.h>
-
#include <string.h>
+#include <glib/gi18n.h>
#include "renderer.h"
@@ -53,87 +53,27 @@ gint themeNameToNumber (const gchar *id)
return 0;
}
-Renderer * rendererFactory (gint id, gint pxw, gint pxh)
+Renderer * rendererFactory (gint id)
{
+ Renderer *r;
switch (id) {
case 2:
- return new TangoBlock (pxw, pxh, TRUE);
+ r = new TangoBlock (TRUE);
case 1:
- return new TangoBlock (pxw, pxh, FALSE);
+ r = new TangoBlock (FALSE);
case 0:
default:
- return new Renderer (pxw, pxh, FALSE);
+ r = new Renderer ();
}
+ return r;
}
/* The Renderer class is a basic drawing class that is structured to
- be easily customised by subclasses. The most basic customisation
- would be to override drawCell to customise the drawing of one
- cell. If more sophisticated drawing is required for either the
- foreground or the background is required then drawForeground and
- drawBackground are the functions to alter. If a completely
- different drawing regime is required then the render method - the
- only entry point from external code - can be replaced. */
+ be easily customised by subclasses. Override drawCell to customise
+ the drawing of one cell. */
/* Note that the default renderer is designed to be reasonably fast
- and flexible, not flashy. Also note that the renderer may be used
- for the preview widget and possibly the theme previewer, so make no
- assumptions. */
-
-Renderer::Renderer (gint pxw, gint pxh, bool initFromSubclass)
-{
- pxwidth = pxw == 0 ? 1 : pxw;
- pxheight = pxh == 0 ? 1 : pxh;
- for (int i = 0; i < NCOLOURS; i++) {
- cache[i] = NULL;
- }
- if (!initFromSubclass)
- rescaleCache (pxwidth, pxheight);
-}
-
-Renderer::~Renderer ()
-{
- for (int i = 0; i<NCOLOURS; i++) {
- if (cache[i])
- cairo_surface_destroy (cache[i]);
- }
-}
-
-cairo_surface_t* Renderer::getCacheCellById (gint id)
-{
- return cache[id];
-}
-
-void Renderer::rescaleCache (gint x, gint y)
-{
- if (x == 0 or y == 0)
- return;
-
- pxwidth = x;
- pxheight = y;
-
- if(cache[0]) {
- for (int i = 0; i<NCOLOURS; i++) {
- g_object_unref (cache[i]);
- cache[i] = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- pxwidth,
- pxheight);
- cairo_t *cr = cairo_create (cache[i]);
- cairo_scale (cr, 1.0 * pxwidth, 1.0 * pxheight);
- drawCell (cr, i);
- cairo_destroy (cr);
- }
- } else {
- for (int i = 0; i<NCOLOURS; i++) {
- cache[i] = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- pxwidth, pxheight);
- cairo_t *cr = cairo_create (cache[i]);
- cairo_scale (cr, 1.0 * pxwidth, 1.0 * pxheight);
- drawCell (cr, i);
- cairo_destroy (cr);
- }
- }
-}
+ and flexible, not flashy. */
void Renderer::drawCell (cairo_t *cr, guint color)
{
@@ -153,10 +93,9 @@ void Renderer::drawCell (cairo_t *cr, guint color)
cairo_paint (cr);
}
-TangoBlock::TangoBlock (gint pxw, gint pxh, gboolean grad) : Renderer (pxw, pxh, TRUE)
+TangoBlock::TangoBlock (gboolean grad) : Renderer ()
{
usegrads = grad;
- rescaleCache (pxwidth, pxheight);
}
void TangoBlock::drawCell (cairo_t *cr, guint color)
diff --git a/gnometris/renderer.h b/gnometris/renderer.h
index 920daea..8341d40 100644
--- a/gnometris/renderer.h
+++ b/gnometris/renderer.h
@@ -28,7 +28,6 @@
#include <glib.h>
#include "blocks.h"
-#include "tetris.h"
struct ThemeTableEntry {
const gchar *name;
@@ -36,35 +35,25 @@ struct ThemeTableEntry {
};
extern const ThemeTableEntry ThemeTable[];
+gint themeNameToNumber (const gchar *id);
class Renderer {
public:
- Renderer (gint pxw, gint pxh, bool initFromSubclass);
- virtual ~ Renderer ();
-
- void rescaleCache (gint pxw, gint pxh);
- cairo_surface_t* getCacheCellById (gint id);
-
- gint pxwidth;
- gint pxheight;
-protected:
- cairo_surface_t* cache[NCOLOURS];
- virtual void drawCell (cairo_t * cr, guint color);
+ virtual void drawCell (cairo_t *cr, guint color);
};
-Renderer *rendererFactory (gint id, gint pxw, gint pxh);
-gint themeNameToNumber (const gchar * id);
+Renderer *rendererFactory (gint id);
class TangoBlock:public Renderer {
public:
- TangoBlock (gint pxw, gint pxh, gboolean grad);
+ TangoBlock (gboolean grad);
+ virtual void drawCell (cairo_t *cr, guint color);
-protected:
- virtual void drawCell (cairo_t * cr, guint color);
+protected:
gboolean usegrads;
private:
- void drawRoundedRectangle (cairo_t * cr, gdouble x, gdouble y, gdouble w, gdouble h, gdouble r);
+ void drawRoundedRectangle (cairo_t *cr, gdouble x, gdouble y, gdouble w, gdouble h, gdouble r);
};
#endif // __renderer_h__
diff --git a/gnometris/tetris.cpp b/gnometris/tetris.cpp
index 3fa92fe..d9e624f 100644
--- a/gnometris/tetris.cpp
+++ b/gnometris/tetris.cpp
@@ -26,8 +26,6 @@
#include <math.h>
#include <ctype.h>
-#include <glib/gi18n.h>
-#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <gio/gio.h>
@@ -43,8 +41,8 @@
#include "scoreframe.h"
#include "highscores.h"
#include "preview.h"
-#include "renderer.h"
#include "blockops.h"
+#include "renderer.h"
int LINES = 20;
int COLUMNS = 14;
diff --git a/gnometris/tetris.h b/gnometris/tetris.h
index 6690a3d..30f214f 100644
--- a/gnometris/tetris.h
+++ b/gnometris/tetris.h
@@ -26,7 +26,7 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
+//#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libgames-support/games-conf.h>
diff --git a/libgames-support/games-debug.c b/libgames-support/games-debug.c
index 46b60dc..a424e8a 100644
--- a/libgames-support/games-debug.c
+++ b/libgames-support/games-debug.c
@@ -33,6 +33,7 @@ _games_debug_init (void)
const GDebugKey keys[] = {
{ "card-theme", GAMES_DEBUG_CARD_THEME },
{ "card-cache", GAMES_DEBUG_CARD_CACHE },
+ { "blocks-cache", GAMES_DEBUG_BLOCKS_CACHE },
{ "runtime", GAMES_DEBUG_RUNTIME },
{ "sound", GAMES_DEBUG_SOUND },
{ "window-state", GAMES_DEBUG_WINDOW_STATE }
diff --git a/libgames-support/games-debug.h b/libgames-support/games-debug.h
index 244aeeb..bd1dcce 100644
--- a/libgames-support/games-debug.h
+++ b/libgames-support/games-debug.h
@@ -30,9 +30,10 @@ G_BEGIN_DECLS
typedef enum {
GAMES_DEBUG_CARD_THEME = 1 << 0,
GAMES_DEBUG_CARD_CACHE = 1 << 1,
- GAMES_DEBUG_RUNTIME = 1 << 2,
- GAMES_DEBUG_SOUND = 1 << 3,
- GAMES_DEBUG_WINDOW_STATE = 1 << 4
+ GAMES_DEBUG_BLOCKS_CACHE = 1 << 2,
+ GAMES_DEBUG_RUNTIME = 1 << 3,
+ GAMES_DEBUG_SOUND = 1 << 4,
+ GAMES_DEBUG_WINDOW_STATE = 1 << 5
} GamesDebugFlags;
#ifdef GNOME_ENABLE_DEBUG
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]