diff options
Diffstat (limited to 'saedit/spritedrawingarea')
-rw-r--r-- | saedit/spritedrawingarea/sdalayer.c | 271 | ||||
-rw-r--r-- | saedit/spritedrawingarea/sdalayer.h | 54 | ||||
-rw-r--r-- | saedit/spritedrawingarea/sdalayerprivate.h | 19 | ||||
-rw-r--r-- | saedit/spritedrawingarea/spritedrawingarea.c | 437 | ||||
-rw-r--r-- | saedit/spritedrawingarea/spritedrawingarea.h | 71 |
5 files changed, 852 insertions, 0 deletions
diff --git a/saedit/spritedrawingarea/sdalayer.c b/saedit/spritedrawingarea/sdalayer.c new file mode 100644 index 0000000..9794b80 --- /dev/null +++ b/saedit/spritedrawingarea/sdalayer.c @@ -0,0 +1,271 @@ +#include "spritedrawingarea.h" +#include "sdalayer.h" +#include "sdalayerprivate.h" + +enum { + PROP_0, + PROP_VISIBLE, + PROP_OFFSET_X, + PROP_OFFSET_Y, + PROP_DRAW_FUNC, + PROP_USER_DATA, + PROP_Z_INDEX, + PROP_COUNT +}; + +static void +sda_layer_get_property ( + GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec +) { + SDALayer *layer = SDA_LAYER (object); + SDALayerPrivate *priv = layer->priv; + + switch (prop_id) { + case PROP_VISIBLE: + g_value_set_boolean ( + value, priv->visible + ); + break; + + case PROP_OFFSET_X: + g_value_set_int ( + value, priv->offset_x + ); + break; + + case PROP_OFFSET_Y: + g_value_set_int ( + value, priv->offset_y + ); + break; + + case PROP_Z_INDEX: + g_value_set_int ( + value, priv->z_index + ); + break; + + case PROP_DRAW_FUNC: + g_value_set_pointer ( + value, (gpointer) priv->draw_func + ); + break; + + case PROP_USER_DATA: + g_value_set_pointer ( + value, priv->user_data + ); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +sda_layer_set_property ( + GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec +) { + SDALayer *layer = SDA_LAYER (object); + SDALayerPrivate *priv = layer->priv; + + switch (prop_id) { + case PROP_VISIBLE: + priv->visible = g_value_get_boolean (value); + break; + + case PROP_OFFSET_X: + priv->offset_x = g_value_get_int (value); + break; + + case PROP_OFFSET_Y: + priv->offset_y = g_value_get_int (value); + break; + + case PROP_Z_INDEX: + priv->z_index = g_value_get_int (value); + break; + + case PROP_DRAW_FUNC: + priv->draw_func = (SDALayerDrawFunc) g_value_get_pointer (value); + break; + + case PROP_USER_DATA: + priv->user_data = g_value_get_pointer (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +void +sda_layer_init ( + SDALayer *layer, + SDALayerClass *class +) { + layer->priv = G_TYPE_INSTANCE_GET_PRIVATE ( + layer, + SDA_TYPE_LAYER, + SDALayerPrivate + ); + + layer->priv->draw_func = NULL; + layer->priv->user_data = NULL; +} + +void +sda_layer_class_init ( + SDALayerClass *klass, + gpointer class_data +) { + GObjectClass *object_class; + + g_type_class_add_private (klass, sizeof (SDALayerPrivate)); + + object_class = G_OBJECT_CLASS (klass); + object_class->set_property = sda_layer_set_property; + object_class->get_property = sda_layer_get_property; + + g_object_class_install_property ( + object_class, + PROP_VISIBLE, + g_param_spec_boolean ( + "visible", + "Visible", + "Whether this layer is visible", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT + ) + ); + + g_object_class_install_property ( + object_class, + PROP_OFFSET_X, + g_param_spec_int ( + "offset-x", + "Offset X", + "The X coordinate of the layer offset", + -SPRITE_DRAWING_AREA_FIELD_SIZE, + SPRITE_DRAWING_AREA_FIELD_SIZE, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT + ) + ); + + g_object_class_install_property ( + object_class, + PROP_OFFSET_Y, + g_param_spec_int ( + "offset-y", + "Offset y", + "The Y coordinate of the layer offset", + -SPRITE_DRAWING_AREA_FIELD_SIZE, + SPRITE_DRAWING_AREA_FIELD_SIZE, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT + ) + ); + + g_object_class_install_property ( + object_class, + PROP_DRAW_FUNC, + g_param_spec_pointer ( + "draw-func", + "Draw function", + "A function invoked to draw the layer", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY + ) + ); + + g_object_class_install_property ( + object_class, + PROP_USER_DATA, + g_param_spec_pointer ( + "user-data", + "User data", + "Data that will be propagated to the draw" + " function upon call", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT + ) + ); + + g_object_class_install_property ( + object_class, + PROP_Z_INDEX, + g_param_spec_int ( + "z-index", + "Z-index", + "Z-index of the layer", + -1024, 1024, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT + ) + ); +} + +GType +sda_layer_get_type (void) { + static GType sda_layer_type = 0; + + if (sda_layer_type == 0) { + const GTypeInfo sda_layer_info = { + sizeof (SDALayerClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) sda_layer_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (SDALayer), + 0, /* n_preallocs */ + (GInstanceInitFunc) sda_layer_init, + NULL, /* value_table */ + }; + + sda_layer_type = g_type_register_static ( + G_TYPE_OBJECT, + "SDALayer", + &sda_layer_info, + 0 + ); + } + + return sda_layer_type; +} + +SDALayer *sda_layer_new ( + SDALayerDrawFunc draw_func, + gpointer user_data +) { + return g_object_new ( + SDA_TYPE_LAYER, + "draw-func", draw_func, + "user-data", user_data, + NULL + ); +} + +gint +sda_layer_compare_by_z_index ( + const SDALayer *a, + const SDALayer *b +) { + return a->priv->z_index - b->priv->z_index; +} + +void +sda_layer_set_z_index (SDALayer *layer, gint z_index) { + g_object_set (layer, "z-index", z_index, NULL); +} + +void +sda_layer_set_visible (SDALayer *layer, gboolean visible) { + g_object_set (layer, "visible", visible, NULL); +} diff --git a/saedit/spritedrawingarea/sdalayer.h b/saedit/spritedrawingarea/sdalayer.h new file mode 100644 index 0000000..e1bac04 --- /dev/null +++ b/saedit/spritedrawingarea/sdalayer.h @@ -0,0 +1,54 @@ +#ifndef _SDALAYER_H_ +#define _SDALAYER_H_ + +#include <glib-object.h> +#include <cairo.h> + +G_BEGIN_DECLS + +#define SDA_TYPE_LAYER (sda_layer_get_type ()) +#define SDA_LAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SDA_TYPE_LAYER, SDALayer)) +#define SDA_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SDA_TYPE_LAYER, SDALayerClass)) +#define IS_SDA_LAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SDA_TYPE_LAYER)) +#define IS_SDA_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SDA_TYPE_LAYER)) +#define SDA_LAYER_GET_CLASS(obj) ((obj), SDA_TYPE_LAYER, SDALayerClass) + +typedef struct _SDALayer SDALayer; +typedef struct _SDALayerClass SDALayerClass; +typedef struct _SDALayerPrivate SDALayerPrivate; + +struct _SDALayerClass { + GObjectClass parent_class; +}; + +GType +sda_layer_get_type (void); + +typedef void +(* SDALayerDrawFunc) ( + SDALayer *layer, + cairo_t *cr, + gpointer user_data +); + +SDALayer * +sda_layer_new ( + SDALayerDrawFunc draw_func, + gpointer user_data +); + +gint +sda_layer_compare_by_z_index ( + const SDALayer *a, + const SDALayer *b +); + +void +sda_layer_set_z_index (SDALayer *layer, gint z_index); + +void +sda_layer_set_visible (SDALayer *layer, gboolean visible); + +G_END_DECLS + +#endif diff --git a/saedit/spritedrawingarea/sdalayerprivate.h b/saedit/spritedrawingarea/sdalayerprivate.h new file mode 100644 index 0000000..daf47bc --- /dev/null +++ b/saedit/spritedrawingarea/sdalayerprivate.h @@ -0,0 +1,19 @@ +#ifndef _SDALAYERPRIVATE_H_ +#define _SDALAYERPRIVATE_H_ + +struct _SDALayerPrivate { + gboolean visible; + gint offset_x, offset_y; + gint z_index; + + SDALayerDrawFunc draw_func; + gpointer user_data; +}; + +struct _SDALayer { + GObject object; + + SDALayerPrivate *priv; +}; + +#endif diff --git a/saedit/spritedrawingarea/spritedrawingarea.c b/saedit/spritedrawingarea/spritedrawingarea.c new file mode 100644 index 0000000..376c8e1 --- /dev/null +++ b/saedit/spritedrawingarea/spritedrawingarea.c @@ -0,0 +1,437 @@ +#include "spritedrawingarea.h" +#include "sdalayer.h" +#include "sdalayerprivate.h" + +struct _SpriteDrawingAreaPrivate { + gint center_x, center_y; + gdouble scale_factor; + + gboolean drag_active; + gdouble drag_x, drag_y; + + GList *layers; +}; + +enum { + PROP_0, + PROP_CENTER_X, + PROP_CENTER_Y, + PROP_SCALE_FACTOR, + PROP_COUNT +}; + +void +sprite_drawing_area_get_center ( + SpriteDrawingArea *sdarea, + gint *center_x, + gint *center_y +) { + g_object_get ( + sdarea, + "center-x", center_x, + "center-y", center_y, + NULL + ); +} + +void +sprite_drawing_area_set_center ( + SpriteDrawingArea *sdarea, + gint center_x, + gint center_y +) { + g_object_set ( + sdarea, + "center-x", center_x, + "center-y", center_y, + NULL + ); +} + +gdouble +sprite_drawing_area_get_scale_factor ( + SpriteDrawingArea *sdarea +) { + gdouble result; + + g_object_get ( + sdarea, + "scale-factor", &result, + NULL + ); + + return result; +} + +void +sprite_drawing_area_set_scale_factor ( + SpriteDrawingArea *sdarea, + gdouble scale_factor +) { + g_object_set ( + sdarea, + "scale-factor", scale_factor, + NULL + ); +} + +static gboolean +_sprite_drawing_area_draw_handler ( + GtkWidget *widget, + cairo_t *cr, + gpointer user_data +) { + SpriteDrawingArea *sdarea = SPRITE_DRAWING_AREA (widget); + GList *l; + + gint width = gtk_widget_get_allocated_width (widget); + gint height = gtk_widget_get_allocated_height (widget); + + gdouble scale = sprite_drawing_area_get_scale_factor (sdarea); + + gint center_x, center_y; + + sprite_drawing_area_get_center (sdarea, ¢er_x, ¢er_y); + + cairo_translate ( + cr, + 0.5 * (gdouble) width, + 0.5 * (gdouble) height + ); + + cairo_scale (cr, scale, scale); + + cairo_translate ( + cr, + -center_x, + -center_y + ); + + sdarea->priv->layers = g_list_sort ( + sdarea->priv->layers, + (GCompareFunc) sda_layer_compare_by_z_index + ); + + for (l = sdarea->priv->layers; l != NULL; l = l->next) { + SDALayer *layer = SDA_LAYER (l->data); + + if (!layer->priv->visible) + continue; + + cairo_save (cr); + + cairo_translate ( + cr, + layer->priv->offset_x, + layer->priv->offset_y + ); + + if (layer->priv->draw_func != NULL) + layer->priv->draw_func (layer, cr, layer->priv->user_data); + + cairo_restore (cr); + } + + return FALSE; +} + +static void +sprite_drawing_area_get_property ( + GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec +) { + SpriteDrawingArea *sdarea = SPRITE_DRAWING_AREA (object); + + switch (prop_id) { + case PROP_CENTER_X: + g_value_set_int ( + value, sdarea->priv->center_x + ); + break; + + case PROP_CENTER_Y: + g_value_set_int ( + value, sdarea->priv->center_y + ); + break; + + case PROP_SCALE_FACTOR: + g_value_set_double ( + value, sdarea->priv->scale_factor + ); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +sprite_drawing_area_set_property ( + GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec +) { + SpriteDrawingArea *sdarea = SPRITE_DRAWING_AREA (object); + + switch (prop_id) { + case PROP_CENTER_X: + sdarea->priv->center_x = g_value_get_int (value); + break; + + case PROP_CENTER_Y: + sdarea->priv->center_y = g_value_get_int (value); + break; + + case PROP_SCALE_FACTOR: + sdarea->priv->scale_factor = g_value_get_double (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +gboolean +_sprite_drawing_area_drag_start_callback ( + GtkWidget *widget, + GdkEvent *event, + gpointer user_data +) { + SpriteDrawingArea *sdarea = SPRITE_DRAWING_AREA (widget); + + if (event->button.button != 1) + return FALSE; + + sdarea->priv->drag_active = TRUE; + sdarea->priv->drag_x = event->button.x; + sdarea->priv->drag_y = event->button.y; + + return FALSE; +} + +gboolean +_sprite_drawing_area_drag_end_callback ( + GtkWidget *widget, + GdkEvent *event, + gpointer user_data +) { + SpriteDrawingArea *sdarea = SPRITE_DRAWING_AREA (widget); + + if (event->button.button != 1) + return FALSE; + + sdarea->priv->drag_active = FALSE; + return FALSE; +} + +gboolean +_sprite_drawing_area_drag_motion_callback ( + GtkWidget *widget, + GdkEvent *event, + gpointer user_data +) { + SpriteDrawingArea *sdarea = SPRITE_DRAWING_AREA (widget); + + gdouble event_x, event_y; + + gint center_x, center_y; + gint delta_x, delta_y; + + gdouble scale_factor; + + if ((event->motion.state & GDK_BUTTON1_MASK) == 0) + return FALSE; + + if (!sdarea->priv->drag_active) + return FALSE; + + event_x = event->motion.x; + event_y = event->motion.y; + + sprite_drawing_area_get_center (sdarea, ¢er_x, ¢er_y); + + scale_factor = sprite_drawing_area_get_scale_factor (sdarea); + + delta_x = + (gint) (event_x / scale_factor + 0.5) - (gint) (sdarea->priv->drag_x / scale_factor + 0.5); + delta_y = + (gint) (event_y / scale_factor + 0.5) - (gint) (sdarea->priv->drag_y / scale_factor + 0.5); + + sprite_drawing_area_set_center ( + sdarea, + center_x - delta_x, + center_y - delta_y + ); + + sdarea->priv->drag_x = event_x; + sdarea->priv->drag_y = event_y; + + gtk_widget_queue_draw (widget); + return FALSE; +} + +static void +sprite_drawing_area_init ( + SpriteDrawingArea *sdarea, + SpriteDrawingAreaClass *klass +) { + /* Setting up private */ + sdarea->priv = G_TYPE_INSTANCE_GET_PRIVATE ( + sdarea, + TYPE_SPRITE_DRAWING_AREA, + SpriteDrawingAreaPrivate + ); + + sdarea->priv->layers = NULL; + + g_signal_connect ( + sdarea, + "button-press-event", + (GCallback) _sprite_drawing_area_drag_start_callback, + NULL + ); + + g_signal_connect ( + sdarea, + "button-release-event", + (GCallback) _sprite_drawing_area_drag_end_callback, + NULL + ); + + g_signal_connect ( + sdarea, + "motion-notify-event", + (GCallback) _sprite_drawing_area_drag_motion_callback, + NULL + ); +} + +static void +sprite_drawing_area_class_init ( + SpriteDrawingAreaClass *klass, + gpointer class_data +) { + GObjectClass *object_class; + + g_type_class_add_private (klass, sizeof (SpriteDrawingAreaPrivate)); + + object_class = G_OBJECT_CLASS (klass); + object_class->set_property = sprite_drawing_area_set_property; + object_class->get_property = sprite_drawing_area_get_property; + + g_signal_override_class_handler ( + "draw", + TYPE_SPRITE_DRAWING_AREA, + (GCallback) _sprite_drawing_area_draw_handler + ); + + g_object_class_install_property ( + object_class, + PROP_CENTER_X, + g_param_spec_int ( + "center-x", + "Center X", + "The X coordinate of the point on the field " + "camera is centered on, in pixels", + -SPRITE_DRAWING_AREA_FIELD_SIZE, + SPRITE_DRAWING_AREA_FIELD_SIZE, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT + ) + ); + + g_object_class_install_property ( + object_class, + PROP_CENTER_Y, + g_param_spec_int ( + "center-y", + "Center Y", + "The Y coordinate of the point on the field " + "camera is centered on, in pixels", + -SPRITE_DRAWING_AREA_FIELD_SIZE, + SPRITE_DRAWING_AREA_FIELD_SIZE, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT + ) + ); + + g_object_class_install_property ( + object_class, + PROP_SCALE_FACTOR, + g_param_spec_double ( + "scale-factor", + "Scale factor", + "The scaling factor that is used in making " + "the camera zooming effect", + 0.01, 100.0, 1.0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT + ) + ); +} + +GType +sprite_drawing_area_get_type (void) { + static GType sdarea_type = 0; + + if (sdarea_type == 0) { + const GTypeInfo sdarea_info = { + sizeof (SpriteDrawingAreaClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) sprite_drawing_area_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (SpriteDrawingArea), + 0, /* n_preallocs */ + (GInstanceInitFunc) sprite_drawing_area_init, + NULL, /* value_table */ + }; + + sdarea_type = g_type_register_static ( + GTK_TYPE_DRAWING_AREA, + "SpriteDrawingArea", + &sdarea_info, + 0 + ); + + } + + return sdarea_type; +} + +GtkWidget * +sprite_drawing_area_new (void) { + GtkWidget *sdarea = GTK_WIDGET ( + g_object_new (TYPE_SPRITE_DRAWING_AREA, NULL) + ); + return sdarea; +} + +void +sprite_drawing_area_add_layer ( + SpriteDrawingArea *sdarea, + SDALayer *layer +) { + sdarea->priv->layers = g_list_insert_sorted ( + sdarea->priv->layers, + layer, + (GCompareFunc) sda_layer_compare_by_z_index + ); +} + +void +sprite_drawing_area_remove_layer ( + SpriteDrawingArea *sdarea, + SDALayer *layer +) { + sdarea->priv->layers = g_list_remove ( + sdarea->priv->layers, + layer + ); +} diff --git a/saedit/spritedrawingarea/spritedrawingarea.h b/saedit/spritedrawingarea/spritedrawingarea.h new file mode 100644 index 0000000..ee3aa6d --- /dev/null +++ b/saedit/spritedrawingarea/spritedrawingarea.h @@ -0,0 +1,71 @@ +#ifndef __SPRITE_DRAWING_AREA_H__ +#define __SPRITE_DRAWING_AREA_H__ + +#include <gdk/gdk.h> +#include <gtk/gtk.h> +#include "sdalayer.h" + +G_BEGIN_DECLS + +#define TYPE_SPRITE_DRAWING_AREA (sprite_drawing_area_get_type ()) +#define SPRITE_DRAWING_AREA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SPRITE_DRAWING_AREA, SpriteDrawingArea)) +#define SPRITE_DRAWING_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SPRITE_DRAWING_AREA, SpriteDrawingAreaClass)) +#define IS_SPRITE_DRAWING_AREA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SPRITE_DRAWING_AREA)) +#define IS_SPRITE_DRAWING_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SPRITE_DRAWING_AREA)) +#define SPRITE_DRAWING_AREA_GET_CLASS(obj) ((obj), TYPE_SPRITE_DRAWING_AREA, SpriteDrawingAreaClass) + +typedef struct _SpriteDrawingArea SpriteDrawingArea; +typedef struct _SpriteDrawingAreaPrivate SpriteDrawingAreaPrivate; +typedef struct _SpriteDrawingAreaClass SpriteDrawingAreaClass; + +struct _SpriteDrawingArea { + GtkDrawingArea darea; + + SpriteDrawingAreaPrivate *priv; +}; + +struct _SpriteDrawingAreaClass { + GtkDrawingAreaClass darea_class; + + void (* draw_field) ( + GtkWidget *sdarea, + gpointer data + ); +}; + +static const gint SPRITE_DRAWING_AREA_FIELD_SIZE = 1024; + +GType +sprite_drawing_area_get_type (void); + +GtkWidget* +sprite_drawing_area_new (void); + +void +sprite_drawing_area_set_scale_factor ( + SpriteDrawingArea *sdarea, + gdouble scale_factor +); + +void +sprite_drawing_area_add_layer ( + SpriteDrawingArea *sdarea, + SDALayer *layer +); + +void +sprite_drawing_area_remove_layer ( + SpriteDrawingArea *sdarea, + SDALayer *layer +); + +void +sprite_drawing_area_set_center ( + SpriteDrawingArea *sdarea, + gint center_x, + gint center_y +); + +G_END_DECLS + +#endif |