zoomedit: Man kann R?ume hinzuf?gen, yeah!
This commit is contained in:
parent
4d035c6455
commit
8dc800c372
9 changed files with 399 additions and 146 deletions
117
draw.c
117
draw.c
|
@ -31,30 +31,34 @@ static void drawGrid(cairo_t *cr, const RECTANGLE *rect) {
|
||||||
cairo_move_to(cr, d, rect->y);
|
cairo_move_to(cr, d, rect->y);
|
||||||
cairo_line_to(cr, d, rect->y+rect->height);
|
cairo_line_to(cr, d, rect->y+rect->height);
|
||||||
|
|
||||||
if(step > 0.5)
|
if(step > 0.005) {
|
||||||
string = g_strdup_printf("%i", (int)rint(d));
|
if(step > 0.5)
|
||||||
else
|
string = g_strdup_printf("%i", (int)d);
|
||||||
string = g_strdup_printf("%.*f", -(int)floor(log10(step*1.1)), d+step/10);
|
else
|
||||||
|
string = g_strdup_printf("%.*f", -(int)floor(log10(step*1.1)), d+step/10);
|
||||||
cairo_move_to(cr, d+1/scale, rect->y+11/scale);
|
|
||||||
cairo_show_text(cr, string);
|
cairo_move_to(cr, d+1/scale, rect->y+11/scale);
|
||||||
|
cairo_show_text(cr, string);
|
||||||
g_free(string);
|
|
||||||
|
g_free(string);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(d = rect->y - fmod(rect->y, step) - step; d <= rect->y+rect->height; d+=step) {
|
for(d = rect->y - fmod(rect->y, step) - step; d <= rect->y+rect->height; d+=step) {
|
||||||
cairo_move_to(cr, rect->x, d);
|
cairo_move_to(cr, rect->x, d);
|
||||||
cairo_line_to(cr, rect->x+rect->width, d);
|
cairo_line_to(cr, rect->x+rect->width, d);
|
||||||
|
|
||||||
if(step > 0.5)
|
if(step > 0.005) {
|
||||||
string = g_strdup_printf("%i", (int)rint(d));
|
if(step > 0.5)
|
||||||
else
|
string = g_strdup_printf("%i", (int)d);
|
||||||
string = g_strdup_printf("%.*f", -(int)floor(log10(step*1.1)), d+step/10);
|
else
|
||||||
|
string = g_strdup_printf("%.*f", -(int)floor(log10(step*1.1)), d+step/10);
|
||||||
cairo_move_to(cr, rect->x+3/scale, d+11/scale);
|
|
||||||
cairo_show_text(cr, string);
|
cairo_move_to(cr, rect->x+3/scale, d+11/scale);
|
||||||
|
cairo_show_text(cr, string);
|
||||||
g_free(string);
|
|
||||||
|
g_free(string);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_stroke(cr);
|
cairo_stroke(cr);
|
||||||
|
@ -63,7 +67,7 @@ static void drawGrid(cairo_t *cr, const RECTANGLE *rect) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void polygon2path(cairo_t *cr, const POLYGON *polygon, const RECTANGLE *rect) {
|
static void polygon2path(cairo_t *cr, const POLYGON *polygon, const RECTANGLE *rect, gboolean close) {
|
||||||
int i;
|
int i;
|
||||||
POLYGON polygon2 = {0, NULL};
|
POLYGON polygon2 = {0, NULL};
|
||||||
|
|
||||||
|
@ -83,7 +87,8 @@ static void polygon2path(cairo_t *cr, const POLYGON *polygon, const RECTANGLE *r
|
||||||
cairo_line_to(cr, polygon2.vertices[i].x, polygon2.vertices[i].y);
|
cairo_line_to(cr, polygon2.vertices[i].x, polygon2.vertices[i].y);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_close_path(cr);
|
if(close)
|
||||||
|
cairo_close_path(cr);
|
||||||
|
|
||||||
if(rect && polygon2.vertices)
|
if(rect && polygon2.vertices)
|
||||||
free(polygon2.vertices);
|
free(polygon2.vertices);
|
||||||
|
@ -93,9 +98,11 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
VERTEX v1 = {-1, -1}, v2 = {widget->allocation.width+1, widget->allocation.height+1};
|
VERTEX v1 = {-1, -1}, v2 = {widget->allocation.width+1, widget->allocation.height+1};
|
||||||
RECTANGLE rect;
|
RECTANGLE rect;
|
||||||
|
gboolean vertexOk;
|
||||||
static GdkPixmap *pixmap = NULL;
|
static GdkPixmap *pixmap = NULL;
|
||||||
static double lastImageWidth = 0.0, lastImageHeight = 0.0;
|
static double lastImageWidth = 0.0, lastImageHeight = 0.0;
|
||||||
static gint lastWidth = 0.0, lastHeight = 0.0;
|
static gint lastWidth = 0.0, lastHeight = 0.0;
|
||||||
|
static int lastEditMode = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,8 +116,8 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
|
||||||
rect.width = v2.x-v1.x;
|
rect.width = v2.x-v1.x;
|
||||||
rect.height = v2.y-v1.y;
|
rect.height = v2.y-v1.y;
|
||||||
|
|
||||||
if(pixmap == NULL || lastImageWidth != getImageWidth() || lastImageHeight != getImageHeight() ||
|
if(pixmap == NULL || fabs(lastImageWidth - getImageWidth()) >= 0.000001 || fabs(lastImageHeight - getImageHeight()) >= 0.000001 ||
|
||||||
lastWidth != widget->allocation.width || lastHeight != widget->allocation.height || repaint)
|
lastWidth != widget->allocation.width || lastHeight != widget->allocation.height || lastEditMode != getEditMode() || repaint)
|
||||||
{
|
{
|
||||||
if(pixmap != NULL)
|
if(pixmap != NULL)
|
||||||
g_object_unref(G_OBJECT(pixmap));
|
g_object_unref(G_OBJECT(pixmap));
|
||||||
|
@ -121,15 +128,17 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
|
||||||
lastImageHeight = getImageHeight();
|
lastImageHeight = getImageHeight();
|
||||||
lastWidth = widget->allocation.width;
|
lastWidth = widget->allocation.width;
|
||||||
lastHeight = widget->allocation.height;
|
lastHeight = widget->allocation.height;
|
||||||
|
lastEditMode = getEditMode();
|
||||||
repaint = FALSE;
|
repaint = FALSE;
|
||||||
|
|
||||||
|
|
||||||
cr = gdk_cairo_create(GDK_DRAWABLE(pixmap));
|
cr = gdk_cairo_create(GDK_DRAWABLE(pixmap));
|
||||||
|
|
||||||
cairo_translate(cr, getImageWidth()/2-xTranslate, getImageHeight()/2-yTranslate);
|
cairo_translate(cr, getImageWidth()/2-xTranslate, getImageHeight()/2-yTranslate);
|
||||||
cairo_scale(cr, scale, scale);
|
cairo_scale(cr, scale, scale);
|
||||||
|
|
||||||
cairo_set_line_width(cr, 1.0/scale);
|
cairo_set_line_width(cr, 1.0/scale);
|
||||||
cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
|
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
|
||||||
|
|
||||||
cairo_set_source_rgb(cr, 0, 0, 0);
|
cairo_set_source_rgb(cr, 0, 0, 0);
|
||||||
cairo_paint(cr);
|
cairo_paint(cr);
|
||||||
|
@ -138,7 +147,7 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
|
||||||
|
|
||||||
for(i = 0; i < getLevel()->nRooms; i++) {
|
for(i = 0; i < getLevel()->nRooms; i++) {
|
||||||
if(&getLevel()->rooms[i] != getActiveRoom())
|
if(&getLevel()->rooms[i] != getActiveRoom())
|
||||||
polygon2path(cr, &getLevel()->rooms[i].polygon, &rect);
|
polygon2path(cr, &getLevel()->rooms[i].polygon, &rect, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.3);
|
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.3);
|
||||||
|
@ -148,13 +157,14 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
|
||||||
cairo_stroke(cr);
|
cairo_stroke(cr);
|
||||||
|
|
||||||
if(getEditMode() == EDIT_MODE_SELECTED) {
|
if(getEditMode() == EDIT_MODE_SELECTED) {
|
||||||
polygon2path(cr, &getActiveRoom()->polygon, &rect);
|
polygon2path(cr, &getActiveRoom()->polygon, &rect, TRUE);
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.2);
|
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.2);
|
||||||
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, 2.0/scale);
|
cairo_set_line_width(cr, 2.0/scale);
|
||||||
|
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
|
||||||
cairo_stroke(cr);
|
cairo_stroke(cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,24 +173,57 @@ 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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
if(getHoveredRoom() != NULL && getHoveredRoom() != getActiveRoom() &&
|
if(getHoveredRoom() != NULL && getHoveredRoom() != getActiveRoom() &&
|
||||||
(getEditMode() == EDIT_MODE_VIEW || getEditMode() == EDIT_MODE_SELECTED))
|
(getEditMode() == EDIT_MODE_VIEW || getEditMode() == EDIT_MODE_SELECTED))
|
||||||
{
|
{
|
||||||
cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
|
polygon2path(cr, &getHoveredRoom()->polygon, &rect, TRUE);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
polygon2path(cr, &getHoveredRoom()->polygon, &rect);
|
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.7);
|
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.7);
|
||||||
cairo_stroke(cr);
|
cairo_stroke(cr);
|
||||||
|
|
||||||
cairo_destroy (cr);
|
|
||||||
}
|
}
|
||||||
|
else if(getEditMode() == EDIT_MODE_ADD) {
|
||||||
|
polygon2path(cr, &getActiveRoom()->polygon, NULL, FALSE);
|
||||||
|
|
||||||
|
if(isPolygonOk(&getActiveRoom()->polygon))
|
||||||
|
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.2);
|
||||||
|
else
|
||||||
|
cairo_set_source_rgba(cr, 1.0, 0.3, 0.3, 0.2);
|
||||||
|
cairo_fill_preserve(cr);
|
||||||
|
|
||||||
|
|
||||||
|
if(getActiveRoom()->polygon.nVertices && getHoveredVertex()) {
|
||||||
|
vertexOk = isVertexOk(getHoveredVertex());
|
||||||
|
|
||||||
|
if(vertexOk)
|
||||||
|
cairo_line_to(cr, getHoveredVertex()->x, getHoveredVertex()->y);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_set_line_width(cr, 2.0/scale);
|
||||||
|
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
|
||||||
|
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
|
||||||
|
cairo_set_source_rgba(cr, 0.0, 0.7, 1.0, 0.7);
|
||||||
|
cairo_stroke(cr);
|
||||||
|
|
||||||
|
if(getActiveRoom()->polygon.nVertices && getHoveredVertex() && !vertexOk) {
|
||||||
|
cairo_set_source_rgba(cr, 1.0, 0.3, 0.3, 0.7);
|
||||||
|
|
||||||
|
i = getActiveRoom()->polygon.nVertices - 1;
|
||||||
|
cairo_move_to(cr, getActiveRoom()->polygon.vertices[i].x, getActiveRoom()->polygon.vertices[i].y);
|
||||||
|
cairo_line_to(cr, getHoveredVertex()->x, getHoveredVertex()->y);
|
||||||
|
|
||||||
|
cairo_stroke(cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_destroy (cr);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +234,7 @@ double getScale() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void setScale(double s) {
|
void setScale(double s) {
|
||||||
scale = s;
|
scale = MAX(0.005, MIN(s, 10000));
|
||||||
repaint = TRUE;
|
repaint = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
149
edit.c
149
edit.c
|
@ -1,4 +1,7 @@
|
||||||
#include "edit.h"
|
#include "edit.h"
|
||||||
|
#include "level.h"
|
||||||
|
#include "geometry.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
static int editMode = EDIT_MODE_VIEW;
|
static int editMode = EDIT_MODE_VIEW;
|
||||||
|
@ -6,6 +9,8 @@ static int editMode = EDIT_MODE_VIEW;
|
||||||
static ROOM *activeRoom = NULL;
|
static ROOM *activeRoom = NULL;
|
||||||
static ROOM *hoveredRoom = NULL;
|
static ROOM *hoveredRoom = NULL;
|
||||||
|
|
||||||
|
static VERTEX hoveredVertex;
|
||||||
|
static int hasHoveredVertex = 0;
|
||||||
|
|
||||||
int getEditMode() {
|
int getEditMode() {
|
||||||
return editMode;
|
return editMode;
|
||||||
|
@ -18,14 +23,150 @@ ROOM *getActiveRoom() {
|
||||||
void setActiveRoom(ROOM *room) {
|
void setActiveRoom(ROOM *room) {
|
||||||
activeRoom = room;
|
activeRoom = room;
|
||||||
|
|
||||||
if(editMode == EDIT_MODE_VIEW || editMode == EDIT_MODE_SELECTED)
|
if(room == NULL) {
|
||||||
editMode = (room == NULL) ? EDIT_MODE_VIEW : EDIT_MODE_SELECTED;
|
editMode = EDIT_MODE_VIEW;
|
||||||
|
}
|
||||||
|
else if(editMode == EDIT_MODE_VIEW) {
|
||||||
|
editMode = EDIT_MODE_SELECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VERTEX *getHoveredVertex() {
|
||||||
|
if(hasHoveredVertex) return &hoveredVertex;
|
||||||
|
else return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHoveredVertex(VERTEX *v) {
|
||||||
|
int i;
|
||||||
|
LEVEL *l;
|
||||||
|
|
||||||
|
if(v) {
|
||||||
|
hasHoveredVertex = 1;
|
||||||
|
hoveredVertex = *v;
|
||||||
|
|
||||||
|
l = getLevel();
|
||||||
|
hoveredRoom = NULL;
|
||||||
|
|
||||||
|
for(i = 0; i < l->nRooms; i++) {
|
||||||
|
if(vertexInPolygon(v, &l->rooms[i].polygon)) {
|
||||||
|
hoveredRoom = &l->rooms[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hasHoveredVertex = 0;
|
||||||
|
hoveredRoom = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startAddMode() {
|
||||||
|
ROOM room = {{0, NULL}, calloc(1, sizeof(unsigned char))};
|
||||||
|
|
||||||
|
activeRoom = calloc(1, sizeof(ROOM));
|
||||||
|
activeRoom->polygon.nVertices = 0;
|
||||||
|
activeRoom->polygon.vertices = NULL;
|
||||||
|
activeRoom->name = calloc(1, sizeof(unsigned char));
|
||||||
|
|
||||||
|
editMode = EDIT_MODE_ADD;
|
||||||
|
}
|
||||||
|
|
||||||
|
void endAddMode() {
|
||||||
|
editMode = activeRoom ? EDIT_MODE_SELECTED : EDIT_MODE_VIEW;
|
||||||
}
|
}
|
||||||
|
|
||||||
ROOM *getHoveredRoom() {
|
ROOM *getHoveredRoom() {
|
||||||
return hoveredRoom;
|
return hoveredRoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setHoveredRoom(ROOM *room) {
|
static isLineOk(LINE *l) {
|
||||||
hoveredRoom = room;
|
LEVEL *lvl = getLevel();
|
||||||
|
LINE l2;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
if(activeRoom) {
|
||||||
|
for(i = 0; i+2 < activeRoom->polygon.nVertices; i++) {
|
||||||
|
l2.v1 = activeRoom->polygon.vertices[i];
|
||||||
|
l2.v2 = activeRoom->polygon.vertices[i+1];
|
||||||
|
|
||||||
|
if(lineIntersection(l, &l2, NULL) == INTERSECTION_SEGMENT_SEGMENT) return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(activeRoom->polygon.nVertices > 1) {
|
||||||
|
l2.v1 = activeRoom->polygon.vertices[activeRoom->polygon.nVertices-2];
|
||||||
|
l2.v2 = activeRoom->polygon.vertices[activeRoom->polygon.nVertices-1];
|
||||||
|
if(vertexOnLine(&l->v2, &l2)) return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < lvl->nRooms; i++) {
|
||||||
|
if(linePolygonIntersection(l, &lvl->rooms[i].polygon))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int isVertexOk(VERTEX *v) {
|
||||||
|
LEVEL *lvl = getLevel();
|
||||||
|
LINE l;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < lvl->nRooms; i++) {
|
||||||
|
if(vertexInPolygon(v, &lvl->rooms[i].polygon)) return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(getActiveRoom() && getActiveRoom()->polygon.nVertices))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
l.v1 = getActiveRoom()->polygon.vertices[getActiveRoom()->polygon.nVertices-1];
|
||||||
|
l.v2 = *v;
|
||||||
|
|
||||||
|
return isLineOk(&l);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int isPolygonOk(POLYGON *polygon) {
|
||||||
|
LEVEL *lvl = getLevel();
|
||||||
|
LINE l, l2;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if(!polygon->nVertices) return 0;
|
||||||
|
|
||||||
|
for(i = 0; i < lvl->nRooms; i++) {
|
||||||
|
if(!lvl->rooms[i].polygon.nVertices) continue;
|
||||||
|
|
||||||
|
if(vertexInPolygon(&polygon->vertices[0], &lvl->rooms[i].polygon))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(vertexInPolygon(&lvl->rooms[i].polygon.vertices[0], polygon))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(polygon->nVertices == 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for(i = 0; i < polygon->nVertices; i++) {
|
||||||
|
l.v1 = polygon->vertices[i];
|
||||||
|
l.v2 = polygon->vertices[(i+1)%polygon->nVertices];
|
||||||
|
|
||||||
|
for(j = 0; j < lvl->nRooms; j++) {
|
||||||
|
if(linePolygonIntersection(&l, &lvl->rooms[j].polygon))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(j = i+2; j < polygon->nVertices; j++) {
|
||||||
|
if(i == 0 && j == polygon->nVertices-1) continue;
|
||||||
|
|
||||||
|
l2.v1 = polygon->vertices[j];
|
||||||
|
l2.v2 = polygon->vertices[(j+1)%polygon->nVertices];
|
||||||
|
|
||||||
|
if(lineIntersection(&l, &l2, NULL) == INTERSECTION_SEGMENT_SEGMENT)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
8
edit.h
8
edit.h
|
@ -2,6 +2,7 @@
|
||||||
#define EDIT_H_
|
#define EDIT_H_
|
||||||
|
|
||||||
#include "level.h"
|
#include "level.h"
|
||||||
|
#include "geometry.h"
|
||||||
|
|
||||||
#define EDIT_MODE_VIEW 0
|
#define EDIT_MODE_VIEW 0
|
||||||
#define EDIT_MODE_SELECTED 1
|
#define EDIT_MODE_SELECTED 1
|
||||||
|
@ -13,6 +14,11 @@ ROOM *getActiveRoom();
|
||||||
void setActiveRoom(ROOM *room);
|
void setActiveRoom(ROOM *room);
|
||||||
|
|
||||||
ROOM *getHoveredRoom();
|
ROOM *getHoveredRoom();
|
||||||
void setHoveredRoom(ROOM *room);
|
|
||||||
|
VERTEX *getHoveredVertex();
|
||||||
|
void setHoveredVertex(VERTEX *v);
|
||||||
|
|
||||||
|
int isVertexOk(VERTEX *v);
|
||||||
|
int isPolygonOk(POLYGON *polygon);
|
||||||
|
|
||||||
#endif /*EDIT_H_*/
|
#endif /*EDIT_H_*/
|
||||||
|
|
46
geometry.c
46
geometry.c
|
@ -4,13 +4,13 @@
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
|
||||||
void addVertex(VERTEX_LIST *list, VERTEX *v) {
|
void addVertex(VERTEX_LIST *list, const VERTEX *v) {
|
||||||
list->nVertices++;
|
list->nVertices++;
|
||||||
list->vertices = realloc(list->vertices, list->nVertices*sizeof(VERTEX));
|
list->vertices = realloc(list->vertices, list->nVertices*sizeof(VERTEX));
|
||||||
list->vertices[list->nVertices-1] = *v;
|
list->vertices[list->nVertices-1] = *v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertVertex(VERTEX_LIST *list, VERTEX *v, unsigned int n) {
|
void insertVertex(VERTEX_LIST *list, const VERTEX *v, unsigned int n) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(n > list->nVertices)
|
if(n > list->nVertices)
|
||||||
|
@ -44,6 +44,27 @@ double vertexDistance(const VERTEX *v1, const VERTEX *v2) {
|
||||||
return sqrt(vertexDistanceSquare(v1, v2));
|
return sqrt(vertexDistanceSquare(v1, v2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vertexOnLine(const VERTEX *v, const LINE *l) {
|
||||||
|
if(l->v1.x == l->v2.x && l->v1.y == l->v2.y) {
|
||||||
|
if(l->v1.x == v->x && l->v1.y == v->y) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l->v1.x == l->v2.x) {
|
||||||
|
if(l->v1.x != v->x) return 0;
|
||||||
|
else if(v->y >= MIN(l->v1.y, l->v2.y) && v->y <= MAX(l->v1.y, l->v2.y)) return 1;
|
||||||
|
else return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l->v1.y == l->v2.y) {
|
||||||
|
if(l->v1.y != v->y) return 0;
|
||||||
|
else if(v->x >= MIN(l->v1.x, l->v2.x) && v->x <= MAX(l->v1.x, l->v2.x)) return 1;
|
||||||
|
else return 1;
|
||||||
|
}
|
||||||
|
if((v->x-l->v1.x)/(l->v2.x-l->v1.x) - (v->y-l->v1.y)/(l->v2.y-l->v1.y) == 0) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int vertexInRect(const VERTEX *v, const RECTANGLE *rect) {
|
int vertexInRect(const VERTEX *v, const RECTANGLE *rect) {
|
||||||
int ret = EDGE_NONE;
|
int ret = EDGE_NONE;
|
||||||
|
|
||||||
|
@ -149,7 +170,7 @@ double polygonArea(const POLYGON *p) {
|
||||||
for(i = 0; i < p->nVertices; i++)
|
for(i = 0; i < p->nVertices; i++)
|
||||||
d += (p->vertices[(i+1)%p->nVertices].x+p->vertices[i].x)*(p->vertices[(i+1)%p->nVertices].y-p->vertices[i].y);
|
d += (p->vertices[(i+1)%p->nVertices].x+p->vertices[i].x)*(p->vertices[(i+1)%p->nVertices].y-p->vertices[i].y);
|
||||||
|
|
||||||
return d/2;
|
return fabs(d/2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lineIntersection(const LINE *la, const LINE *lb, VERTEX *v) {
|
int lineIntersection(const LINE *la, const LINE *lb, VERTEX *v) {
|
||||||
|
@ -176,22 +197,25 @@ int lineIntersection(const LINE *la, const LINE *lb, VERTEX *v) {
|
||||||
switched = 1;
|
switched = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
double ma = (ya2-ya1)/(xa2-xa1);
|
if(xa1 == xa2 && xb1 == xb2)
|
||||||
double mb = (yb2-yb1)/(xb2-xb1);
|
return (xa1 == xb1) ? INTERSECTION_IDENTICAL : INTERSECTION_NONE;
|
||||||
double ba = ya1 - ma*xa1;
|
|
||||||
double bb = yb1 - mb*xb1;
|
|
||||||
|
|
||||||
if(ma == mb) return (ba == bb) ? INTERSECTION_IDENTICAL : INTERSECTION_NONE;
|
if(xa1 == xa2) {
|
||||||
|
|
||||||
if(isinf(ma)) {
|
|
||||||
v->x = xa1;
|
v->x = xa1;
|
||||||
v->y = yb1;
|
v->y = yb1;
|
||||||
}
|
}
|
||||||
else if(isinf(mb)) {
|
else if(xb1 == xb2) {
|
||||||
v->x = xb1;
|
v->x = xb1;
|
||||||
v->y = ya1;
|
v->y = ya1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
double ma = (ya2-ya1)/(xa2-xa1);
|
||||||
|
double mb = (yb2-yb1)/(xb2-xb1);
|
||||||
|
double ba = ya1 - ma*xa1;
|
||||||
|
double bb = yb1 - mb*xb1;
|
||||||
|
|
||||||
|
if(ma == mb) return (ba == bb) ? INTERSECTION_IDENTICAL : INTERSECTION_NONE;
|
||||||
|
|
||||||
v->x = (bb-ba)/(ma-mb);
|
v->x = (bb-ba)/(ma-mb);
|
||||||
v->y = ma*v->x + ba;
|
v->y = ma*v->x + ba;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,13 +39,14 @@ typedef struct _VERTEX_LIST {
|
||||||
} VERTEX_LIST, POLYGON;
|
} VERTEX_LIST, POLYGON;
|
||||||
|
|
||||||
|
|
||||||
void addVertex(VERTEX_LIST *list, VERTEX *v);
|
void addVertex(VERTEX_LIST *list, const VERTEX *v);
|
||||||
void insertVertex(VERTEX_LIST *list, VERTEX *v, unsigned int n);
|
void insertVertex(VERTEX_LIST *list, const VERTEX *v, unsigned int n);
|
||||||
void deleteVertex(VERTEX_LIST *list, unsigned int n);
|
void deleteVertex(VERTEX_LIST *list, unsigned int n);
|
||||||
|
|
||||||
double vertexDistanceSquare(const VERTEX *v1, const VERTEX *v2);
|
double vertexDistanceSquare(const VERTEX *v1, const VERTEX *v2);
|
||||||
double vertexDistance(const VERTEX *v1, const VERTEX *v2);
|
double vertexDistance(const VERTEX *v1, const VERTEX *v2);
|
||||||
|
|
||||||
|
int vertexOnLine(const VERTEX *v, const LINE *l);
|
||||||
int vertexInRect(const VERTEX *v, const RECTANGLE *rect);
|
int vertexInRect(const VERTEX *v, const RECTANGLE *rect);
|
||||||
gboolean vertexInPolygon(const VERTEX *v, const POLYGON *p);
|
gboolean vertexInPolygon(const VERTEX *v, const POLYGON *p);
|
||||||
|
|
||||||
|
|
2
level.c
2
level.c
|
@ -13,7 +13,7 @@ void setLevel(LEVEL *l) {
|
||||||
level = l;
|
level = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addRoom(LEVEL *lvl, ROOM *room) {
|
void addRoom(LEVEL *lvl, const ROOM *room) {
|
||||||
lvl->nRooms++;
|
lvl->nRooms++;
|
||||||
lvl->rooms = realloc(lvl->rooms, lvl->nRooms*sizeof(ROOM));
|
lvl->rooms = realloc(lvl->rooms, lvl->nRooms*sizeof(ROOM));
|
||||||
lvl->rooms[lvl->nRooms-1] = *room;
|
lvl->rooms[lvl->nRooms-1] = *room;
|
||||||
|
|
2
level.h
2
level.h
|
@ -17,7 +17,7 @@ typedef struct _LEVEL {
|
||||||
LEVEL *getLevel();
|
LEVEL *getLevel();
|
||||||
void setLevel(LEVEL *l);
|
void setLevel(LEVEL *l);
|
||||||
|
|
||||||
void addRoom(LEVEL *lvl, ROOM *room);
|
void addRoom(LEVEL *lvl, const ROOM *room);
|
||||||
void deleteRoom(LEVEL *lvl, unsigned int n);
|
void deleteRoom(LEVEL *lvl, unsigned int n);
|
||||||
|
|
||||||
void freeLevel(LEVEL *lvl);
|
void freeLevel(LEVEL *lvl);
|
||||||
|
|
205
window.c
205
window.c
|
@ -8,10 +8,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
static GtkWidget *drawingArea = NULL, *sidebar = NULL;
|
static GtkWidget *drawingArea = NULL, *sidebarView = NULL, *sidebarAdd = NULL;
|
||||||
static GtkAdjustment *hAdjustment = NULL, *vAdjustment = NULL;
|
static GtkAdjustment *hAdjustment = NULL, *vAdjustment = NULL;
|
||||||
|
|
||||||
static GtkWidget *entryName, *labelArea = NULL, *labelPerimeter = NULL;
|
static GtkWidget *entryName, *labelArea = NULL, *labelPerimeter = NULL, *buttonAdd = NULL, *buttonAddDo = NULL;
|
||||||
|
|
||||||
|
|
||||||
static gboolean deleteEvent(GtkWidget *widget, GdkEvent *event, gpointer data) {
|
static gboolean deleteEvent(GtkWidget *widget, GdkEvent *event, gpointer data) {
|
||||||
|
@ -32,27 +32,30 @@ static gboolean scrollEvent(GtkWidget *widget, GdkEventScroll *event, gpointer u
|
||||||
|
|
||||||
static gboolean buttonEvent(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
|
static gboolean buttonEvent(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
|
||||||
VERTEX v = {event->x, event->y};
|
VERTEX v = {event->x, event->y};
|
||||||
int i;
|
|
||||||
|
|
||||||
switch(event->type) {
|
switch(event->type) {
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
switch(event->button) {
|
switch(event->button) {
|
||||||
case 1:
|
case 1:
|
||||||
viewToImage(&v);
|
switch(getEditMode()) {
|
||||||
|
case EDIT_MODE_VIEW:
|
||||||
setActiveRoom(NULL);
|
case EDIT_MODE_SELECTED:
|
||||||
|
setActiveRoom(getHoveredRoom());
|
||||||
for(i = 0; i < getLevel()->nRooms; i++) {
|
|
||||||
if(vertexInPolygon(&v, &getLevel()->rooms[i].polygon)) {
|
updateSidebar();
|
||||||
setActiveRoom(&getLevel()->rooms[i]);
|
|
||||||
|
redraw();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
case EDIT_MODE_ADD:
|
||||||
|
viewToImage(&v);
|
||||||
|
|
||||||
|
if(isVertexOk(&v)) {
|
||||||
|
addVertex(&getActiveRoom()->polygon, &v);
|
||||||
|
updateSidebar();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSidebar();
|
|
||||||
|
|
||||||
redraw();
|
|
||||||
gtk_widget_queue_draw(drawingArea);
|
gtk_widget_queue_draw(drawingArea);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,64 +64,40 @@ static gboolean buttonEvent(GtkWidget *widget, GdkEventButton *event, gpointer u
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean crossingNotifyEvent(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data) {
|
gboolean crossingNotifyEvent(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data) {
|
||||||
int i;
|
|
||||||
VERTEX v;
|
VERTEX v;
|
||||||
|
|
||||||
|
|
||||||
setHoveredRoom(NULL);
|
switch(event->type) {
|
||||||
|
case GDK_ENTER_NOTIFY:
|
||||||
if(event->type == GDK_ENTER_NOTIFY) {
|
v.x = event->x;
|
||||||
v.x = event->x;
|
v.y = event->y;
|
||||||
v.y = event->y;
|
|
||||||
|
viewToImage(&v);
|
||||||
|
|
||||||
viewToImage(&v);
|
setHoveredVertex(&v);
|
||||||
|
|
||||||
|
break;
|
||||||
for(i = 0; i < getLevel()->nRooms; i++) {
|
case GDK_LEAVE_NOTIFY:
|
||||||
if(vertexInPolygon(&v, &getLevel()->rooms[i].polygon)) {
|
setHoveredVertex(NULL);
|
||||||
setHoveredRoom(&getLevel()->rooms[i]);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gtk_widget_queue_draw(drawingArea);
|
gtk_widget_queue_draw(drawingArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean motionNotifyEvent(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) {
|
gboolean motionNotifyEvent(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) {
|
||||||
int i;
|
VERTEX v;
|
||||||
static VERTEX v, v_last = {0, 0};
|
ROOM *last = getHoveredRoom();
|
||||||
LINE line;
|
|
||||||
gboolean changed = FALSE;
|
|
||||||
|
|
||||||
v.x = event->x;
|
v.x = event->x;
|
||||||
v.y = event->y;
|
v.y = event->y;
|
||||||
|
|
||||||
viewToImage(&v);
|
viewToImage(&v);
|
||||||
|
|
||||||
line.v1 = v_last;
|
setHoveredVertex(&v);
|
||||||
line.v2 = v;
|
|
||||||
|
|
||||||
for(i = 0; i < getLevel()->nRooms; i++) {
|
if(getHoveredRoom() != last || getEditMode() == EDIT_MODE_ADD)
|
||||||
if(linePolygonIntersection(&line, &getLevel()->rooms[i].polygon)) {
|
|
||||||
if(vertexInPolygon(&v, &getLevel()->rooms[i].polygon)) {
|
|
||||||
setHoveredRoom(&getLevel()->rooms[i]);
|
|
||||||
changed = TRUE;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
setHoveredRoom(NULL);
|
|
||||||
changed = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(changed)
|
|
||||||
gtk_widget_queue_draw(drawingArea);
|
gtk_widget_queue_draw(drawingArea);
|
||||||
|
|
||||||
v_last = v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroy(GtkWidget *widget, gpointer data) {
|
static void destroy(GtkWidget *widget, gpointer data) {
|
||||||
|
@ -182,31 +161,56 @@ static void sidebarNameChanged(GtkEditable *editable, gpointer user_data) {
|
||||||
getActiveRoom()->name = strdup(gtk_entry_get_text(GTK_ENTRY(entryName)));
|
getActiveRoom()->name = strdup(gtk_entry_get_text(GTK_ENTRY(entryName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sidebarButtonClicked(GtkButton *button, gpointer user_data) {
|
||||||
|
if(button == GTK_BUTTON(buttonAdd)) {
|
||||||
|
startAddMode();
|
||||||
|
updateSidebar();
|
||||||
|
|
||||||
|
gtk_widget_queue_draw(drawingArea);
|
||||||
|
}
|
||||||
|
else if(button == GTK_BUTTON(buttonAddDo)) {
|
||||||
|
if(getActiveRoom() &&getActiveRoom()->polygon.nVertices > 2 && isPolygonOk(&getActiveRoom()->polygon)) {
|
||||||
|
addRoom(getLevel(), getActiveRoom());
|
||||||
|
setActiveRoom(&getLevel()->rooms[getLevel()->nRooms-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
endAddMode();
|
||||||
|
updateSidebar();
|
||||||
|
|
||||||
|
gtk_widget_queue_draw(drawingArea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GtkWidget* createSidebar() {
|
static GtkWidget* createSidebar() {
|
||||||
GtkWidget *widget, *labelRoomInfo, *labelName, *tableRoomData, *labelAreaLabel, *labelPerimeterLabel;
|
GtkWidget *sidebar, *labelRoomInfo, *labelName;
|
||||||
|
GtkWidget *tableRoomData, *labelAreaLabel, *labelPerimeterLabel;
|
||||||
|
|
||||||
widget = gtk_vbox_new(FALSE, 0);
|
sidebar = gtk_hbox_new(FALSE, 0);
|
||||||
|
|
||||||
|
// View sidebar
|
||||||
|
sidebarView = gtk_vbox_new(FALSE, 0);
|
||||||
|
gtk_box_pack_start(GTK_BOX(sidebar), sidebarView, FALSE, FALSE, 5);
|
||||||
|
|
||||||
labelRoomInfo = gtk_label_new(NULL);
|
labelRoomInfo = gtk_label_new(NULL);
|
||||||
gtk_label_set_markup(GTK_LABEL(labelRoomInfo), "<b>Room info:</b>");
|
gtk_label_set_markup(GTK_LABEL(labelRoomInfo), "<b>Room info:</b>");
|
||||||
gtk_misc_set_alignment(GTK_MISC(labelRoomInfo), 0.0, 0.5);
|
gtk_misc_set_alignment(GTK_MISC(labelRoomInfo), 0.0, 0.5);
|
||||||
gtk_box_pack_start(GTK_BOX(widget), labelRoomInfo, FALSE, FALSE, 5);
|
gtk_box_pack_start(GTK_BOX(sidebarView), labelRoomInfo, FALSE, FALSE, 5);
|
||||||
|
|
||||||
gtk_box_pack_start(GTK_BOX(widget), gtk_hseparator_new(), FALSE, FALSE, 5);
|
gtk_box_pack_start(GTK_BOX(sidebarView), gtk_hseparator_new(), FALSE, FALSE, 5);
|
||||||
|
|
||||||
labelName = gtk_label_new("Name:");
|
labelName = gtk_label_new("Name:");
|
||||||
gtk_misc_set_alignment(GTK_MISC(labelName), 0.0, 0.5);
|
gtk_misc_set_alignment(GTK_MISC(labelName), 0.0, 0.5);
|
||||||
gtk_box_pack_start(GTK_BOX(widget), labelName, FALSE, FALSE, 0);
|
gtk_box_pack_start(GTK_BOX(sidebarView), labelName, FALSE, FALSE, 0);
|
||||||
|
|
||||||
entryName = gtk_entry_new();
|
entryName = gtk_entry_new();
|
||||||
gtk_widget_set_sensitive(entryName, FALSE);
|
gtk_widget_set_sensitive(entryName, FALSE);
|
||||||
g_signal_connect(G_OBJECT(entryName), "changed", G_CALLBACK(sidebarNameChanged), NULL);
|
g_signal_connect(G_OBJECT(entryName), "changed", G_CALLBACK(sidebarNameChanged), NULL);
|
||||||
gtk_box_pack_start(GTK_BOX(widget), entryName, FALSE, FALSE, 0);
|
gtk_box_pack_start(GTK_BOX(sidebarView), entryName, FALSE, FALSE, 0);
|
||||||
|
|
||||||
tableRoomData = gtk_table_new(2, 2, FALSE);
|
tableRoomData = gtk_table_new(2, 2, FALSE);
|
||||||
gtk_table_set_row_spacings(GTK_TABLE(tableRoomData), 5);
|
gtk_table_set_row_spacings(GTK_TABLE(tableRoomData), 5);
|
||||||
gtk_table_set_col_spacings(GTK_TABLE(tableRoomData), 10);
|
gtk_table_set_col_spacings(GTK_TABLE(tableRoomData), 10);
|
||||||
gtk_box_pack_start(GTK_BOX(widget), tableRoomData, FALSE, FALSE, 5);
|
gtk_box_pack_start(GTK_BOX(sidebarView), tableRoomData, FALSE, FALSE, 5);
|
||||||
|
|
||||||
labelAreaLabel = gtk_label_new("Room area:");
|
labelAreaLabel = gtk_label_new("Room area:");
|
||||||
gtk_misc_set_alignment(GTK_MISC(labelAreaLabel), 0.0, 0.5);
|
gtk_misc_set_alignment(GTK_MISC(labelAreaLabel), 0.0, 0.5);
|
||||||
|
@ -224,11 +228,28 @@ static GtkWidget* createSidebar() {
|
||||||
gtk_misc_set_alignment(GTK_MISC(labelPerimeter), 1.0, 0.5);
|
gtk_misc_set_alignment(GTK_MISC(labelPerimeter), 1.0, 0.5);
|
||||||
gtk_table_attach_defaults(GTK_TABLE(tableRoomData), labelPerimeter, 1, 2, 1, 2);
|
gtk_table_attach_defaults(GTK_TABLE(tableRoomData), labelPerimeter, 1, 2, 1, 2);
|
||||||
|
|
||||||
return widget;
|
buttonAdd = gtk_button_new_with_label("Add room");
|
||||||
|
g_signal_connect(G_OBJECT(buttonAdd), "clicked", G_CALLBACK(sidebarButtonClicked), NULL);
|
||||||
|
gtk_box_pack_end(GTK_BOX(sidebarView), buttonAdd, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
// Add sidebar
|
||||||
|
sidebarAdd = gtk_vbox_new(FALSE, 0);
|
||||||
|
gtk_box_pack_start(GTK_BOX(sidebar), sidebarAdd, FALSE, FALSE, 5);
|
||||||
|
|
||||||
|
labelRoomInfo = gtk_label_new(NULL);
|
||||||
|
gtk_label_set_markup(GTK_LABEL(labelRoomInfo), "<b>Add room</b>");
|
||||||
|
gtk_misc_set_alignment(GTK_MISC(labelRoomInfo), 0.0, 0.5);
|
||||||
|
gtk_box_pack_start(GTK_BOX(sidebarAdd), labelRoomInfo, FALSE, FALSE, 5);
|
||||||
|
|
||||||
|
buttonAddDo = gtk_button_new_with_label("Add room");
|
||||||
|
g_signal_connect(G_OBJECT(buttonAddDo), "clicked", G_CALLBACK(sidebarButtonClicked), NULL);
|
||||||
|
gtk_box_pack_end(GTK_BOX(sidebarAdd), buttonAddDo, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
return sidebar;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* createMainWindow() {
|
GtkWidget* createMainWindow() {
|
||||||
GtkWidget *window, *vbox, *hPaned, *table, *vScroll, *hScroll;
|
GtkWidget *window, *hPaned, *vbox, *table, *vScroll, *hScroll, *sidebar;
|
||||||
GdkColor color = {0, 0, 0, 0};
|
GdkColor color = {0, 0, 0, 0};
|
||||||
|
|
||||||
|
|
||||||
|
@ -262,7 +283,6 @@ GtkWidget* createMainWindow() {
|
||||||
g_signal_connect(G_OBJECT(drawingArea), "motion-notify-event", G_CALLBACK(motionNotifyEvent), 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 | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_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));
|
||||||
|
@ -279,6 +299,7 @@ GtkWidget* createMainWindow() {
|
||||||
gtk_paned_pack2(GTK_PANED(hPaned), sidebar, FALSE, TRUE);
|
gtk_paned_pack2(GTK_PANED(hPaned), sidebar, FALSE, TRUE);
|
||||||
|
|
||||||
gtk_widget_show_all(vbox);
|
gtk_widget_show_all(vbox);
|
||||||
|
gtk_widget_hide(sidebarAdd);
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
@ -286,25 +307,43 @@ GtkWidget* createMainWindow() {
|
||||||
void updateSidebar() {
|
void updateSidebar() {
|
||||||
gchar *string;
|
gchar *string;
|
||||||
|
|
||||||
|
switch(getEditMode()) {
|
||||||
if(getActiveRoom()) {
|
case EDIT_MODE_VIEW:
|
||||||
gtk_entry_set_text(GTK_ENTRY(entryName), getActiveRoom()->name);
|
case EDIT_MODE_SELECTED:
|
||||||
gtk_widget_set_sensitive(entryName, TRUE);
|
gtk_widget_hide(sidebarAdd);
|
||||||
|
gtk_widget_show(sidebarView);
|
||||||
string = g_strdup_printf("%.2f", polygonArea(&getActiveRoom()->polygon));
|
|
||||||
gtk_label_set_text(GTK_LABEL(labelArea), string);
|
if(getActiveRoom()) {
|
||||||
g_free(string);
|
gtk_entry_set_text(GTK_ENTRY(entryName), getActiveRoom()->name);
|
||||||
|
gtk_widget_set_sensitive(entryName, TRUE);
|
||||||
string = g_strdup_printf("%.2f", polygonPerimeter(&getActiveRoom()->polygon));
|
|
||||||
gtk_label_set_text(GTK_LABEL(labelPerimeter), string);
|
string = g_strdup_printf("%.2f", polygonArea(&getActiveRoom()->polygon));
|
||||||
g_free(string);
|
gtk_label_set_text(GTK_LABEL(labelArea), string);
|
||||||
}
|
g_free(string);
|
||||||
else {
|
|
||||||
gtk_entry_set_text(GTK_ENTRY(entryName), "");
|
string = g_strdup_printf("%.2f", polygonPerimeter(&getActiveRoom()->polygon));
|
||||||
gtk_widget_set_sensitive(entryName, FALSE);
|
gtk_label_set_text(GTK_LABEL(labelPerimeter), string);
|
||||||
|
g_free(string);
|
||||||
gtk_label_set_text(GTK_LABEL(labelArea), NULL);
|
}
|
||||||
gtk_label_set_text(GTK_LABEL(labelPerimeter), NULL);
|
else {
|
||||||
|
gtk_entry_set_text(GTK_ENTRY(entryName), "");
|
||||||
|
gtk_widget_set_sensitive(entryName, FALSE);
|
||||||
|
|
||||||
|
gtk_label_set_text(GTK_LABEL(labelArea), NULL);
|
||||||
|
gtk_label_set_text(GTK_LABEL(labelPerimeter), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case EDIT_MODE_ADD:
|
||||||
|
gtk_widget_hide(sidebarView);
|
||||||
|
gtk_widget_show(sidebarAdd);
|
||||||
|
|
||||||
|
if(getActiveRoom()) {
|
||||||
|
if(getActiveRoom()->polygon.nVertices > 2 && isPolygonOk(&getActiveRoom()->polygon))
|
||||||
|
gtk_widget_set_sensitive(buttonAddDo, TRUE);
|
||||||
|
else
|
||||||
|
gtk_widget_set_sensitive(buttonAddDo, FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
zoomedit.c
11
zoomedit.c
|
@ -5,22 +5,21 @@
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
VERTEX vertices[4] = {{0,-1}, {1,0}, {0,1}, {-1,0}};
|
LEVEL *lvl = calloc(1, sizeof(LEVEL));
|
||||||
ROOM room = {{sizeof(vertices)/sizeof(vertices[0]), vertices}, calloc(1, sizeof(unsigned char))};
|
|
||||||
LEVEL lvl = {1, &room};
|
|
||||||
GtkWidget *window;
|
GtkWidget *window;
|
||||||
|
|
||||||
|
|
||||||
|
setLevel(lvl);
|
||||||
|
|
||||||
gtk_init(&argc, &argv);
|
gtk_init(&argc, &argv);
|
||||||
|
|
||||||
window = createMainWindow();
|
window = createMainWindow();
|
||||||
|
|
||||||
setLevel(&lvl);
|
|
||||||
|
|
||||||
gtk_widget_show(window);
|
gtk_widget_show(window);
|
||||||
|
|
||||||
gtk_main();
|
gtk_main();
|
||||||
|
|
||||||
free(room.name);
|
freeLevel(lvl);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue