zoomedit: Added room selection and hover effect.
This commit is contained in:
parent
b8549034be
commit
f10436d816
6 changed files with 124 additions and 5 deletions
21
draw.c
21
draw.c
|
@ -97,7 +97,7 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
if(getLevel() == NULL) return;
|
if(getLevel() == NULL) return FALSE;
|
||||||
|
|
||||||
if(pixmap == NULL || lastImageWidth != getImageWidth() || lastImageHeight != getImageHeight() ||
|
if(pixmap == NULL || lastImageWidth != getImageWidth() || lastImageHeight != getImageHeight() ||
|
||||||
lastWidth != widget->allocation.width || lastHeight != widget->allocation.height || repaint)
|
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_fill_preserve(cr);
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.9);
|
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);
|
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);
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
edit.c
9
edit.c
|
@ -4,6 +4,7 @@
|
||||||
static int editMode = EDIT_MODE_VIEW;
|
static int editMode = EDIT_MODE_VIEW;
|
||||||
|
|
||||||
static ROOM *activeRoom = NULL;
|
static ROOM *activeRoom = NULL;
|
||||||
|
static ROOM *hoveredRoom = NULL;
|
||||||
|
|
||||||
int getEditMode() {
|
int getEditMode() {
|
||||||
return editMode;
|
return editMode;
|
||||||
|
@ -20,3 +21,11 @@ void setActiveRoom(ROOM *room) {
|
||||||
if(editMode == EDIT_MODE_VIEW || editMode == EDIT_MODE_SELECTED)
|
if(editMode == EDIT_MODE_VIEW || editMode == EDIT_MODE_SELECTED)
|
||||||
editMode = (room == NULL) ? EDIT_MODE_VIEW : EDIT_MODE_SELECTED;
|
editMode = (room == NULL) ? EDIT_MODE_VIEW : EDIT_MODE_SELECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ROOM *getHoveredRoom() {
|
||||||
|
return hoveredRoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHoveredRoom(ROOM *room) {
|
||||||
|
hoveredRoom = room;
|
||||||
|
}
|
||||||
|
|
3
edit.h
3
edit.h
|
@ -12,4 +12,7 @@ int getEditMode();
|
||||||
ROOM *getActiveRoom();
|
ROOM *getActiveRoom();
|
||||||
void setActiveRoom(ROOM *room);
|
void setActiveRoom(ROOM *room);
|
||||||
|
|
||||||
|
ROOM *getHoveredRoom();
|
||||||
|
void setHoveredRoom(ROOM *room);
|
||||||
|
|
||||||
#endif /*EDIT_H_*/
|
#endif /*EDIT_H_*/
|
||||||
|
|
18
geometry.c
18
geometry.c
|
@ -140,8 +140,11 @@ int lineIntersection(const LINE *la, const LINE *lb, VERTEX *v) {
|
||||||
double xb2 = lb->v2.x, yb2 = lb->v2.y;
|
double xb2 = lb->v2.x, yb2 = lb->v2.y;
|
||||||
double temp;
|
double temp;
|
||||||
int switched = 0;
|
int switched = 0;
|
||||||
|
VERTEX v2;
|
||||||
|
|
||||||
|
|
||||||
|
if(v == NULL) v = &v2;
|
||||||
|
|
||||||
if(xa1 == xa2 && ya1 == ya2) return INTERSECTION_ERROR;
|
if(xa1 == xa2 && ya1 == ya2) return INTERSECTION_ERROR;
|
||||||
if(xb1 == xb2 && yb1 == yb2) 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;
|
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) {
|
void simplifyPolygon(const POLYGON *in, const RECTANGLE *rect, POLYGON *out) {
|
||||||
int i, j;
|
int i, j;
|
||||||
int a;
|
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 lineIntersection(const LINE *la, const LINE *lb, VERTEX *v);
|
||||||
int lineRectIntersection(const LINE *l, const RECTANGLE *rect, int edge, 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);
|
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);
|
void simplifyPolygon(const POLYGON *in, const RECTANGLE *rect, POLYGON *out);
|
||||||
|
|
||||||
#endif /*GEOMETRY_H_*/
|
#endif /*GEOMETRY_H_*/
|
||||||
|
|
77
window.c
77
window.c
|
@ -55,6 +55,67 @@ static gboolean buttonEvent(GtkWidget *widget, GdkEventButton *event, gpointer u
|
||||||
return FALSE;
|
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) {
|
static void destroy(GtkWidget *widget, gpointer data) {
|
||||||
gtk_main_quit();
|
gtk_main_quit();
|
||||||
}
|
}
|
||||||
|
@ -110,7 +171,7 @@ static void updateScrollbarsCentered() {
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* createMainWindow() {
|
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};
|
GdkColor color = {0, 0, 0, 0};
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,8 +191,11 @@ GtkWidget* createMainWindow() {
|
||||||
|
|
||||||
gtk_window_add_accel_group(GTK_WINDOW(window), getAccels());
|
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);
|
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();
|
drawingArea = gtk_drawing_area_new();
|
||||||
gtk_widget_modify_bg(drawingArea, GTK_WIDGET_STATE(drawingArea), &color);
|
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), "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-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), "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);
|
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);
|
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));
|
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);
|
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);
|
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);
|
gtk_widget_show_all(vbox);
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
|
|
Reference in a new issue