diff options
Diffstat (limited to 'saedit/spritedrawingarea/spritedrawingarea.c')
-rw-r--r-- | saedit/spritedrawingarea/spritedrawingarea.c | 437 |
1 files changed, 437 insertions, 0 deletions
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 + ); +} |