diff options
Diffstat (limited to 'draw.c')
-rw-r--r-- | draw.c | 143 |
1 files changed, 111 insertions, 32 deletions
@@ -1,4 +1,5 @@ #include "draw.h" +#include "edit.h" #include "level.h" #include "geometry.h" #include <math.h> @@ -9,6 +10,7 @@ static double scale = 100.0; static double xTranslate = 0.0, yTranslate = 0.0; +static gboolean repaint = FALSE; static void drawGrid(cairo_t *cr, const RECTANGLE *rect) { @@ -17,13 +19,13 @@ static void drawGrid(cairo_t *cr, const RECTANGLE *rect) { double step = pow(0.1, depth2); double d; int i; - gchar buffer[10]; + gchar buffer[20]; cairo_set_font_size(cr, 10.0/scale); - for(i = 0; 0.2*(depth-depth2+i-1) < 0.3; i++) { - d = MIN(0.2*(depth-depth2+i), 0.3); + for(i = 0; 0.4*(depth-depth2+i-1) < 0.5; i++) { + d = MIN(0.4*(depth-depth2+i), 0.5); cairo_set_source_rgb(cr, d, d, d); for(d = rect->x - fmod(rect->x, step) - step; d <= rect->x+rect->width; d+=step) { @@ -87,58 +89,129 @@ static void room2path(cairo_t *cr, const ROOM *room, const RECTANGLE *rect) { } gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) { - VERTEX vertices[4] = {{-1,-1}, {-1,1}, {1,1}, {1,-1}}; - ROOM room = {sizeof(vertices)/sizeof(vertices[0]), vertices}; - LEVEL lvl = {1, &room}; cairo_t *cr; RECTANGLE rect = {-1, -1, widget->allocation.width+2, widget->allocation.height+2}; + static GdkPixmap *pixmap = NULL; + static double lastImageWidth = 0.0, lastImageHeight = 0.0; + static gint lastWidth = 0.0, lastHeight = 0.0; int i; - cr = gdk_cairo_create(widget->window); + if(getLevel() == NULL) return; - gdk_cairo_region(cr, event->region); - cairo_clip(cr); - - cairo_translate(cr, getImageWidth()/2-xTranslate, getImageHeight()/2-yTranslate); - cairo_scale(cr, scale, scale); - - cairo_device_to_user(cr, &rect.x, &rect.y); - cairo_device_to_user_distance(cr, &rect.width, &rect.height); - - cairo_set_line_width(cr, 1.0/scale); - cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); - - drawGrid(cr, &rect); - - for(i = 0; i < lvl.nRooms; i++) - room2path(cr, &lvl.rooms[i], &rect); - - cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.3); - cairo_fill_preserve(cr); - - cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.7); - cairo_stroke(cr); + if(pixmap == NULL || lastImageWidth != getImageWidth() || lastImageHeight != getImageHeight() || + lastWidth != widget->allocation.width || lastHeight != widget->allocation.height || repaint) + { + if(pixmap != NULL) + g_object_unref(G_OBJECT(pixmap)); + + pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); + + lastImageWidth = getImageWidth(); + lastImageHeight = getImageHeight(); + lastWidth = widget->allocation.width; + lastHeight = widget->allocation.height; + repaint = FALSE; + + cr = gdk_cairo_create(GDK_DRAWABLE(pixmap)); + + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_rectangle(cr, 0, 0, widget->allocation.width, widget->allocation.height); + cairo_fill(cr); + + cairo_translate(cr, getImageWidth()/2-xTranslate, getImageHeight()/2-yTranslate); + cairo_scale(cr, scale, scale); + + cairo_device_to_user(cr, &rect.x, &rect.y); + cairo_device_to_user_distance(cr, &rect.width, &rect.height); + + cairo_set_line_width(cr, 1.0/scale); + cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); + + drawGrid(cr, &rect); + + for(i = 0; i < getLevel()->nRooms; i++) { + if(&getLevel()->rooms[i] != getActiveRoom()) + room2path(cr, &getLevel()->rooms[i], &rect); + } + + cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.3); + cairo_fill_preserve(cr); + + cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.7); + cairo_stroke(cr); + + if(getEditMode() == EDIT_MODE_SELECTED) { + room2path(cr, getActiveRoom(), &rect); + + cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.2); + cairo_fill_preserve(cr); + + cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.9); + cairo_set_line_width(cr, 1.5/scale); + cairo_stroke(cr); + } + + cairo_destroy (cr); + } - cairo_destroy (cr); + gdk_draw_drawable(GDK_DRAWABLE(widget->window), widget->style->fg_gc[GTK_WIDGET_STATE(widget)], GDK_DRAWABLE(pixmap), 0, 0, 0, 0, -1, -1); return FALSE; } + double getScale() { return scale; } void setScale(double s) { scale = s; + repaint = TRUE; +} + +void imageToView(VERTEX *v) { + v->x = v->x*scale+getImageWidth()/2-xTranslate; + v->y = v->y*scale+getImageHeight()/2-yTranslate; +} + +void viewToImage(VERTEX *v) { + v->x = (v->x-getImageWidth()/2+xTranslate)/scale; + v->y = (v->y-getImageHeight()/2+yTranslate)/scale; } double getImageWidth() { - return 5*scale; + const LEVEL *level = getLevel(); + double min = 0.0, max = 0.0; + int i, j; + + if(level) { + for(i = 0; i < level->nRooms; i++) { + for(j = 0; j < level->rooms[i].nVertices; j++) { + min = MIN(min, level->rooms[i].vertices[j].x); + max = MAX(max, level->rooms[i].vertices[j].x); + } + } + } + + return (max-min+10)*scale; } double getImageHeight() { - return 5*scale; + const LEVEL *level = getLevel(); + double min = 0.0, max = 0.0; + int i, j; + + if(level) { + for(i = 0; i < level->nRooms; i++) { + for(j = 0; j < level->rooms[i].nVertices; j++) { + min = MIN(min, level->rooms[i].vertices[j].y); + max = MAX(max, level->rooms[i].vertices[j].y); + } + } + } + + return (max-min+10)*scale; } double getXTranslate() { @@ -147,6 +220,7 @@ double getXTranslate() { void setXTranslate(double x) { xTranslate = x; + repaint = TRUE; } double getYTranslate() { @@ -155,4 +229,9 @@ double getYTranslate() { void setYTranslate(double y) { yTranslate = y; + repaint = TRUE; +} + +void redraw() { + repaint = TRUE; } |