255 lines
5.9 KiB
C++
255 lines
5.9 KiB
C++
#include "draw.h"
|
|
#include "edit.h"
|
|
#include "Rectangle.h"
|
|
#include <math.h>
|
|
#include <gtk/gtk.h>
|
|
#include <gtk/gtkgl.h>
|
|
#include <GL/gl.h>
|
|
|
|
|
|
static double scale = 100.0;
|
|
static double xTranslate = 0.0, yTranslate = 0.0;
|
|
|
|
|
|
static void drawGrid(const Rectangle &rect) {
|
|
double depth = log10(scale)-0.75;
|
|
double depth2 = floor(depth);
|
|
double step = pow(0.1, depth2);
|
|
double d;
|
|
int i;
|
|
//gchar *string;
|
|
double x1 = rect.getVertex1().getX(), y1 = rect.getVertex1().getY();
|
|
double x2 = rect.getVertex2().getX(), y2 = rect.getVertex2().getY();
|
|
|
|
|
|
glBegin(GL_LINES);
|
|
//cairo_set_font_size(cr, 10.0/scale);
|
|
|
|
for(i = 0; 0.4*(depth-depth2+i-1) < 0.5; i++) {
|
|
d = MIN(0.4*(depth-depth2+i), 0.5);
|
|
glColor3d(d, d, d);
|
|
|
|
for(d = x1 - fmod(x1, step) - step; d <= x2; d+=step) {
|
|
glVertex2d(d, y1);
|
|
glVertex2d(d, y2);
|
|
|
|
/*if(step > 0.005) {
|
|
if(step > 0.5)
|
|
string = g_strdup_printf("%i", (int)rint(d));
|
|
else
|
|
string = g_strdup_printf("%.*f", -(int)floor(log10(step*1.1)), d+step/10);
|
|
|
|
cairo_move_to(cr, d+1/scale, y1+11/scale);
|
|
cairo_show_text(cr, string);
|
|
|
|
g_free(string);
|
|
}*/
|
|
}
|
|
|
|
for(d = y1 - fmod(y1, step) - step; d <= y2; d+=step) {
|
|
glVertex2d(x1, d);
|
|
glVertex2d(x2, d);
|
|
|
|
/*if(step > 0.005) {
|
|
if(step > 0.5)
|
|
string = g_strdup_printf("%i", (int)rint(d));
|
|
else
|
|
string = g_strdup_printf("%.*f", -(int)floor(log10(step*1.1)), d+step/10);
|
|
|
|
cairo_move_to(cr, x1+3/scale, d+11/scale);
|
|
cairo_show_text(cr, string);
|
|
|
|
g_free(string);
|
|
}*/
|
|
}
|
|
|
|
step *= 10;
|
|
}
|
|
|
|
glEnd();
|
|
}
|
|
|
|
static void fillPolygon(const Polygon &polygon) {
|
|
std::vector<Triangle> triangles;
|
|
|
|
polygon.triangulate(triangles);
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
|
|
for(std::vector<Triangle>::iterator t = triangles.begin(); t != triangles.end(); t++) {
|
|
glVertex2d(t->getVertexA().getX(), t->getVertexA().getY());
|
|
glVertex2d(t->getVertexB().getX(), t->getVertexB().getY());
|
|
glVertex2d(t->getVertexC().getX(), t->getVertexC().getY());
|
|
}
|
|
|
|
glEnd();
|
|
}
|
|
|
|
static void drawPolygon(const Polygon &polygon, bool close) {
|
|
glBegin(GL_LINE_STRIP);
|
|
|
|
for(Polygon::const_iterator vertex = polygon.begin(); vertex != polygon.end(); vertex++)
|
|
glVertex2d(vertex->getX(), vertex->getY());
|
|
|
|
if(close)
|
|
glVertex2d(polygon.front().getX(), polygon.front().getY());
|
|
|
|
glEnd();
|
|
}
|
|
|
|
gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
|
|
GdkGLContext *context = gtk_widget_get_gl_context(widget);
|
|
GdkGLDrawable *drawable = gtk_widget_get_gl_drawable(widget);
|
|
Vertex v1(0, 0), v2(widget->allocation.width, widget->allocation.height);
|
|
Rectangle rect;
|
|
|
|
|
|
if(getLevel() == NULL) return FALSE;
|
|
|
|
viewToImage(&v1);
|
|
viewToImage(&v2);
|
|
|
|
rect.setVertex1(v1);
|
|
rect.setVertex2(v2);
|
|
|
|
if(!gdk_gl_drawable_gl_begin(drawable, context))
|
|
return FALSE;
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
|
|
glLineWidth(1.0);
|
|
|
|
glTranslated(getImageWidth()/2-xTranslate, getImageHeight()/2-yTranslate, 0);
|
|
glScaled(scale, scale, 1);
|
|
|
|
drawGrid(rect);
|
|
|
|
for(Level::const_iterator room = getLevel()->begin(); room != getLevel()->end(); room++) {
|
|
if(&*room == getActiveRoom() && getEditMode() == EDIT_MODE_ADD) continue;
|
|
|
|
if(&*room == getActiveRoom())
|
|
glColor4d(0.0, 0.7, 1.0, 0.2);
|
|
else
|
|
glColor4d(0.0, 0.7, 1.0, 0.3);
|
|
|
|
fillPolygon(*room);
|
|
|
|
if(&*room == getActiveRoom()) {
|
|
glColor4d(1.0, 1.0, 1.0, 0.9);
|
|
glLineWidth(2.0);
|
|
}
|
|
else if(&*room == getHoveredRoom() && getEditMode() != EDIT_MODE_ADD) {
|
|
glColor4d(0.0, 0.7, 1.0, 0.7);
|
|
glLineWidth(2.0);
|
|
}
|
|
else {
|
|
glColor4d(0.0, 0.7, 1.0, 0.7);
|
|
glLineWidth(1.0);
|
|
}
|
|
|
|
drawPolygon(*room, true);
|
|
}
|
|
|
|
if(getEditMode() == EDIT_MODE_ADD) {
|
|
if(isPolygonOk(getActiveRoom()))
|
|
glColor4d(0.0, 0.7, 1.0, 0.2);
|
|
else
|
|
glColor4d(1.0, 0.3, 0.3, 0.2);
|
|
|
|
fillPolygon(*getActiveRoom());
|
|
|
|
glLineWidth(2.0);
|
|
glColor4d(0.0, 0.7, 1.0, 0.7);
|
|
drawPolygon(*getActiveRoom(), false);
|
|
|
|
if(!getActiveRoom()->empty() && getHoveredVertex()) {
|
|
if(!isVertexOk(getHoveredVertex()))
|
|
glColor4d(1.0, 0.3, 0.3, 0.7);
|
|
|
|
glBegin(GL_LINES);
|
|
|
|
glVertex2d(getActiveRoom()->back().getX(), getActiveRoom()->back().getY());
|
|
glVertex2d(getHoveredVertex()->getX(), getHoveredVertex()->getY());
|
|
|
|
glEnd();
|
|
}
|
|
}
|
|
|
|
glPopMatrix();
|
|
|
|
gdk_gl_drawable_swap_buffers(drawable);
|
|
|
|
gdk_gl_drawable_gl_end(drawable);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
double getScale() {
|
|
return scale;
|
|
}
|
|
|
|
void setScale(double s) {
|
|
scale = MAX(0.005, MIN(s, 10000));
|
|
}
|
|
|
|
void imageToView(Vertex *v) {
|
|
v->setX(v->getX()*scale+getImageWidth()/2-xTranslate);
|
|
v->setY(v->getY()*scale+getImageHeight()/2-yTranslate);
|
|
}
|
|
|
|
void viewToImage(Vertex *v) {
|
|
v->setX((v->getX()-getImageWidth()/2+xTranslate)/scale);
|
|
v->setY((v->getY()-getImageHeight()/2+yTranslate)/scale);
|
|
}
|
|
|
|
double getImageWidth() {
|
|
double min = 0.0, max = 0.0;
|
|
|
|
|
|
if(getLevel()) {
|
|
for(Level::iterator room = getLevel()->begin(); room != getLevel()->end(); room++) {
|
|
for(Room::iterator v = room->begin(); v != room->end(); v++) {
|
|
min = MIN(min, v->getX());
|
|
max = MAX(max, v->getX());
|
|
}
|
|
}
|
|
}
|
|
|
|
return (max-min+10)*scale;
|
|
}
|
|
|
|
double getImageHeight() {
|
|
double min = 0.0, max = 0.0;
|
|
|
|
|
|
if(getLevel()) {
|
|
for(Level::iterator room = getLevel()->begin(); room != getLevel()->end(); room++) {
|
|
for(Room::iterator v = room->begin(); v != room->end(); v++) {
|
|
min = MIN(min, v->getY());
|
|
max = MAX(max, v->getY());
|
|
}
|
|
}
|
|
}
|
|
|
|
return (max-min+10)*scale;
|
|
}
|
|
|
|
double getXTranslate() {
|
|
return xTranslate;
|
|
}
|
|
|
|
void setXTranslate(double x) {
|
|
xTranslate = x;
|
|
}
|
|
|
|
double getYTranslate() {
|
|
return yTranslate;
|
|
}
|
|
|
|
void setYTranslate(double y) {
|
|
yTranslate = y;
|
|
}
|