diff options
-rw-r--r-- | draw.c | 21 | ||||
-rw-r--r-- | edit.c | 9 | ||||
-rw-r--r-- | edit.h | 3 | ||||
-rw-r--r-- | geometry.c | 18 | ||||
-rw-r--r-- | geometry.h | 1 | ||||
-rw-r--r-- | window.c | 77 |
6 files changed, 124 insertions, 5 deletions
@@ -97,7 +97,7 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) { int i; - if(getLevel() == NULL) return; + if(getLevel() == NULL) return FALSE; if(pixmap == NULL || lastImageWidth != getImageWidth() || lastImageHeight != getImageHeight() || lastWidth != widget->allocation.width || lastHeight != widget->allocation.height || repaint) @@ -148,7 +148,7 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) { 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_set_line_width(cr, 2.0/scale); cairo_stroke(cr); } @@ -157,6 +157,23 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) { gdk_draw_drawable(GDK_DRAWABLE(widget->window), widget->style->fg_gc[GTK_WIDGET_STATE(widget)], GDK_DRAWABLE(pixmap), 0, 0, 0, 0, -1, -1); + if(getHoveredRoom() != NULL && getHoveredRoom() != getActiveRoom()) { + cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + + cairo_translate(cr, getImageWidth()/2-xTranslate, getImageHeight()/2-yTranslate); + cairo_scale(cr, scale, scale); + + cairo_set_line_width(cr, 2.0/scale); + cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); + + room2path(cr, getHoveredRoom(), NULL); + + cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.7); + cairo_stroke(cr); + + cairo_destroy (cr); + } + return FALSE; } @@ -4,6 +4,7 @@ static int editMode = EDIT_MODE_VIEW; static ROOM *activeRoom = NULL; +static ROOM *hoveredRoom = NULL; int getEditMode() { return editMode; @@ -20,3 +21,11 @@ void setActiveRoom(ROOM *room) { if(editMode == EDIT_MODE_VIEW || editMode == EDIT_MODE_SELECTED) editMode = (room == NULL) ? EDIT_MODE_VIEW : EDIT_MODE_SELECTED; } + +ROOM *getHoveredRoom() { + return hoveredRoom; +} + +void setHoveredRoom(ROOM *room) { + hoveredRoom = room; +} @@ -12,4 +12,7 @@ int getEditMode(); ROOM *getActiveRoom(); void setActiveRoom(ROOM *room); +ROOM *getHoveredRoom(); +void setHoveredRoom(ROOM *room); + #endif /*EDIT_H_*/ @@ -140,7 +140,10 @@ int lineIntersection(const LINE *la, const LINE *lb, VERTEX *v) { double xb2 = lb->v2.x, yb2 = lb->v2.y; double temp; int switched = 0; + VERTEX v2; + + if(v == NULL) v = &v2; if(xa1 == xa2 && ya1 == ya2) return INTERSECTION_ERROR; if(xb1 == xb2 && yb1 == yb2) return INTERSECTION_ERROR; @@ -227,6 +230,21 @@ int lineRectIntersections(const LINE *line, const RECTANGLE *rect, int edge, VER return ret; } +gboolean linePolygonIntersection(const LINE *l, const POLYGON *p) { + int i; + LINE line; + + for(i = 0; i < p->nVertices; i++) { + line.v1 = p->vertices[i]; + line.v2 = p->vertices[(i+1)%p->nVertices]; + + if(lineIntersection(l, &line, NULL) == INTERSECTION_SEGMENT_SEGMENT) + return TRUE; + } + + return FALSE; +} + void simplifyPolygon(const POLYGON *in, const RECTANGLE *rect, POLYGON *out) { int i, j; int a; @@ -49,6 +49,7 @@ gboolean vertexInPolygon(const VERTEX *v, const POLYGON *p); int lineIntersection(const LINE *la, const LINE *lb, VERTEX *v); int lineRectIntersection(const LINE *l, const RECTANGLE *rect, int edge, VERTEX *v); int lineRectIntersections(const LINE *line, const RECTANGLE *rect, int edge, VERTEX *v1, VERTEX *v2); +gboolean linePolygonIntersection(const LINE *l, const POLYGON *p); void simplifyPolygon(const POLYGON *in, const RECTANGLE *rect, POLYGON *out); #endif /*GEOMETRY_H_*/ @@ -55,6 +55,67 @@ static gboolean buttonEvent(GtkWidget *widget, GdkEventButton *event, gpointer u return FALSE; } +gboolean crossingNotifyEvent(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data) { + int i; + VERTEX v; + + + setHoveredRoom(NULL); + + if(event->type == GDK_ENTER_NOTIFY) { + v.x = event->x; + v.y = event->y; + + viewToImage(&v); + + + for(i = 0; i < getLevel()->nRooms; i++) { + if(vertexInPolygon(&v, &getLevel()->rooms[i])) { + setHoveredRoom(&getLevel()->rooms[i]); + + break; + } + } + } + + gtk_widget_queue_draw(drawingArea); +} + +gboolean motionNotifyEvent(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) { + int i; + static VERTEX v, v_last = {0, 0}; + LINE line; + gboolean changed = FALSE; + + v.x = event->x; + v.y = event->y; + + viewToImage(&v); + + line.v1 = v_last; + line.v2 = v; + + for(i = 0; i < getLevel()->nRooms; i++) { + if(linePolygonIntersection(&line, &getLevel()->rooms[i])) { + if(vertexInPolygon(&v, &getLevel()->rooms[i])) { + setHoveredRoom(&getLevel()->rooms[i]); + changed = TRUE; + + break; + } + else { + setHoveredRoom(NULL); + changed = TRUE; + } + } + } + + if(changed) + gtk_widget_queue_draw(drawingArea); + + v_last = v; +} + static void destroy(GtkWidget *widget, gpointer data) { gtk_main_quit(); } @@ -110,7 +171,7 @@ static void updateScrollbarsCentered() { } GtkWidget* createMainWindow() { - GtkWidget *window, *vbox, *menubar, *toolbar, *table, *vScroll, *hScroll; + GtkWidget *window, *vbox, *menubar, *toolbar, *hPaned, *table, *vScroll, *hScroll, *sidebar; GdkColor color = {0, 0, 0, 0}; @@ -130,8 +191,11 @@ GtkWidget* createMainWindow() { gtk_window_add_accel_group(GTK_WINDOW(window), getAccels()); + hPaned = gtk_hpaned_new(); + gtk_box_pack_end(GTK_BOX(vbox), hPaned, TRUE, TRUE, 0); + table = gtk_table_new(2, 2, FALSE); - gtk_box_pack_end(GTK_BOX(vbox), table, TRUE, TRUE, 0); + gtk_paned_pack1(GTK_PANED(hPaned), table, TRUE, TRUE); drawingArea = gtk_drawing_area_new(); gtk_widget_modify_bg(drawingArea, GTK_WIDGET_STATE(drawingArea), &color); @@ -139,8 +203,12 @@ GtkWidget* createMainWindow() { g_signal_connect(G_OBJECT(drawingArea), "expose-event", G_CALLBACK(drawTopView), NULL); g_signal_connect(G_OBJECT(drawingArea), "button-press-event", G_CALLBACK(buttonEvent), NULL); g_signal_connect(G_OBJECT(drawingArea), "button-release-event", G_CALLBACK(buttonEvent), NULL); + g_signal_connect(G_OBJECT(drawingArea), "enter-notify-event", G_CALLBACK(crossingNotifyEvent), NULL); + g_signal_connect(G_OBJECT(drawingArea), "leave-notify-event", G_CALLBACK(crossingNotifyEvent), NULL); + g_signal_connect(G_OBJECT(drawingArea), "motion-notify-event", G_CALLBACK(motionNotifyEvent), NULL); g_signal_connect(G_OBJECT(drawingArea), "scroll-event", G_CALLBACK(scrollEvent), NULL); - gtk_widget_add_events(drawingArea, GDK_SCROLL_MASK); + gtk_widget_add_events(drawingArea, GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + gtk_widget_set_double_buffered(drawingArea, FALSE); gtk_table_attach(GTK_TABLE(table), drawingArea, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND|GTK_SHRINK, GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0); hAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100)); @@ -153,6 +221,9 @@ GtkWidget* createMainWindow() { g_signal_connect(G_OBJECT(vScroll), "value-changed", G_CALLBACK(refreshScrolling), NULL); gtk_table_attach(GTK_TABLE(table), vScroll, 1, 2, 0, 1, 0, GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0); + sidebar = gtk_vbox_new(FALSE, 0); + gtk_paned_pack2(GTK_PANED(hPaned), sidebar, FALSE, TRUE); + gtk_widget_show_all(vbox); return window; |