2007-10-04 23:38:05 +00:00
|
|
|
#include "Drawer.h"
|
|
|
|
#include "Window.h"
|
|
|
|
#include <GL/gl.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
|
|
|
|
void Drawer::realize(GtkWidget *widget, Drawer *drawer) {
|
|
|
|
GdkGLContext *context = gtk_widget_get_gl_context(widget);
|
|
|
|
GdkGLDrawable *drawable = gtk_widget_get_gl_drawable(widget);
|
|
|
|
|
|
|
|
if(!gdk_gl_drawable_gl_begin(drawable, context))
|
|
|
|
return;
|
|
|
|
|
|
|
|
glClearColor(0, 0, 0, 1);
|
|
|
|
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
|
|
|
glEnable(GL_LINE_SMOOTH);
|
2007-12-14 02:47:03 +00:00
|
|
|
glEnable(GL_POINT_SMOOTH);
|
2007-10-04 23:38:05 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
gdk_gl_drawable_gl_end(drawable);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean Drawer::eventHandler(GtkWidget *widget, GdkEvent *event, Drawer *drawer) {
|
|
|
|
switch(event->type) {
|
|
|
|
case GDK_CONFIGURE:
|
|
|
|
drawer->updateViewport();
|
|
|
|
drawer->updateScrollbars();
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case GDK_EXPOSE:
|
2007-10-23 19:08:04 +00:00
|
|
|
drawer->render();
|
2007-10-04 23:38:05 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case GDK_MOTION_NOTIFY:
|
|
|
|
drawer->updateHoveredPoint(event->motion.x, event->motion.y);
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case GDK_ENTER_NOTIFY:
|
|
|
|
drawer->updateHoveredPoint(event->crossing.x, event->crossing.y);
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case GDK_LEAVE_NOTIFY:
|
2007-10-18 19:18:01 +00:00
|
|
|
drawer->window->getEditManager().setHoveredVertex(NULL);
|
2007-10-04 23:38:05 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case GDK_BUTTON_PRESS:
|
2007-12-24 00:04:02 +00:00
|
|
|
drawer->window->getActiveTool()->getEventHandler()->buttonPress(event->button.button);
|
2007-10-04 23:38:05 +00:00
|
|
|
return TRUE;
|
|
|
|
|
2007-12-25 03:27:03 +00:00
|
|
|
case GDK_BUTTON_RELEASE:
|
|
|
|
drawer->window->getActiveTool()->getEventHandler()->buttonRelease(event->button.button);
|
|
|
|
return TRUE;
|
|
|
|
|
2007-10-04 23:38:05 +00:00
|
|
|
case GDK_SCROLL:
|
|
|
|
switch(event->scroll.direction) {
|
|
|
|
case GDK_SCROLL_UP:
|
|
|
|
drawer->zoom(1, event->scroll.x/widget->allocation.width, event->scroll.y/widget->allocation.height);
|
|
|
|
break;
|
|
|
|
case GDK_SCROLL_DOWN:
|
|
|
|
drawer->zoom(-1, event->scroll.x/widget->allocation.width, event->scroll.y/widget->allocation.height);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawer::valueChanged(GtkAdjustment *adjustment, Drawer *drawer) {
|
|
|
|
drawer->updateScrolling();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Drawer::updateViewport() {
|
|
|
|
GdkGLContext *context = gtk_widget_get_gl_context(drawingArea);
|
|
|
|
GdkGLDrawable *drawable = gtk_widget_get_gl_drawable(drawingArea);
|
|
|
|
|
|
|
|
if(!gdk_gl_drawable_gl_begin(drawable, context))
|
|
|
|
return;
|
|
|
|
|
|
|
|
glViewport(0, 0, getWidth(), getHeight());
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
2007-11-16 01:29:04 +00:00
|
|
|
if(getWidth() != 0 && getHeight() != 0)
|
2007-10-04 23:38:05 +00:00
|
|
|
glScalef(2.0f/getWidth(), -2.0f/getHeight(), 1);
|
|
|
|
|
|
|
|
gdk_gl_drawable_gl_end(drawable);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawer::updateScrolling() {
|
2007-11-16 17:49:00 +00:00
|
|
|
if((getImageWidth())*scale < getWidth())
|
2007-11-16 01:29:04 +00:00
|
|
|
xCenter = 0;
|
2007-10-04 23:38:05 +00:00
|
|
|
else
|
2007-11-16 01:29:04 +00:00
|
|
|
xCenter = gtk_adjustment_get_value(hAdjustment);
|
2007-10-04 23:38:05 +00:00
|
|
|
|
2007-11-16 17:49:00 +00:00
|
|
|
if((getImageHeight())*scale < getHeight())
|
2007-11-16 01:29:04 +00:00
|
|
|
yCenter = 0;
|
2007-10-04 23:38:05 +00:00
|
|
|
else
|
2007-11-16 01:29:04 +00:00
|
|
|
yCenter = gtk_adjustment_get_value(vAdjustment);
|
2007-10-04 23:38:05 +00:00
|
|
|
|
2007-11-16 17:49:00 +00:00
|
|
|
gtk_widget_queue_draw(drawingArea);
|
2007-10-04 23:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Drawer::updateScrollbars(float x, float y) {
|
2007-10-18 23:38:05 +00:00
|
|
|
const gdouble imageWidth = getImageWidth(), imageHeight = getImageHeight();
|
2007-11-16 17:49:00 +00:00
|
|
|
const gdouble minX = -imageWidth/2, maxX = imageWidth/2;
|
|
|
|
const gdouble minY = -imageHeight/2, maxY = imageHeight/2;
|
2007-11-16 01:29:04 +00:00
|
|
|
const gdouble width = getWidth()/scale, height = getHeight()/scale;
|
|
|
|
gdouble lower, upper, pageSize, value;
|
|
|
|
|
2007-10-04 23:38:05 +00:00
|
|
|
|
|
|
|
gdk_window_freeze_updates(drawingArea->window);
|
|
|
|
|
2007-11-16 01:29:04 +00:00
|
|
|
g_object_get(G_OBJECT(hAdjustment), "lower", &lower, "upper", &upper, "page_size", &pageSize, NULL);
|
2007-11-16 17:49:00 +00:00
|
|
|
g_object_set(G_OBJECT(hAdjustment), "lower", minX + width/2, "upper", maxX + width/2, "page_size", width, NULL);
|
2007-10-04 23:38:05 +00:00
|
|
|
gtk_adjustment_changed(hAdjustment);
|
|
|
|
|
2007-11-16 17:49:00 +00:00
|
|
|
if(pageSize > (upper-lower) && width < imageWidth)
|
2007-11-16 01:29:04 +00:00
|
|
|
value = 0;
|
2007-10-04 23:38:05 +00:00
|
|
|
else
|
2007-11-16 01:29:04 +00:00
|
|
|
value = gtk_adjustment_get_value(hAdjustment) + (x-0.5)*pageSize*(pageSize/width-1);
|
2007-11-16 17:49:00 +00:00
|
|
|
gtk_adjustment_set_value(hAdjustment, MAX(MIN(value, maxX - width/2), minX + width/2));
|
2007-10-04 23:38:05 +00:00
|
|
|
|
2007-11-16 01:29:04 +00:00
|
|
|
g_object_get(G_OBJECT(vAdjustment), "lower", &lower, "upper", &upper, "page_size", &pageSize, NULL);
|
2007-11-16 17:49:00 +00:00
|
|
|
g_object_set(G_OBJECT(vAdjustment), "lower", minY + height/2, "upper", maxY + height/2, "page_size", height, NULL);
|
2007-10-04 23:38:05 +00:00
|
|
|
gtk_adjustment_changed(vAdjustment);
|
|
|
|
|
2007-11-16 17:49:00 +00:00
|
|
|
if(pageSize > (upper-lower) && height < imageHeight)
|
2007-11-16 01:29:04 +00:00
|
|
|
value = 0;
|
2007-10-04 23:38:05 +00:00
|
|
|
else
|
2007-11-16 01:29:04 +00:00
|
|
|
value = gtk_adjustment_get_value(vAdjustment) + (y-0.5)*pageSize*(pageSize/height-1);
|
2007-11-16 17:49:00 +00:00
|
|
|
gtk_adjustment_set_value(vAdjustment, MAX(MIN(value, maxY - height/2), minY + height/2));
|
2007-10-04 23:38:05 +00:00
|
|
|
|
|
|
|
gdk_window_thaw_updates(drawingArea->window);
|
|
|
|
|
|
|
|
updateScrolling();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawer::updateHoveredPoint(float x, float y) {
|
|
|
|
Vertex v(x, y);
|
2007-10-18 23:38:05 +00:00
|
|
|
viewToImage(&v);
|
2007-10-18 19:18:01 +00:00
|
|
|
window->getEditManager().setHoveredVertex(&v);
|
2007-10-04 23:38:05 +00:00
|
|
|
}
|
|
|
|
|
2007-10-23 19:08:04 +00:00
|
|
|
void Drawer::render() {
|
|
|
|
GdkGLContext *context = gtk_widget_get_gl_context(drawingArea);
|
|
|
|
GdkGLDrawable *drawable = gtk_widget_get_gl_drawable(drawingArea);
|
|
|
|
|
|
|
|
Rectangle rect(0, 0, drawingArea->allocation.width, drawingArea->allocation.height);
|
|
|
|
|
|
|
|
viewToImage(&rect.getVertex1());
|
|
|
|
viewToImage(&rect.getVertex2());
|
|
|
|
|
|
|
|
if(!gdk_gl_drawable_gl_begin(drawable, context))
|
|
|
|
return;
|
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
|
|
|
|
glScalef(scale, scale, 1);
|
2007-11-16 01:29:04 +00:00
|
|
|
glTranslatef(-xCenter, -yCenter, 0);
|
2007-10-23 19:08:04 +00:00
|
|
|
|
|
|
|
renderer.render(window->getLevel(), rect, scale);
|
|
|
|
|
2007-12-24 00:04:02 +00:00
|
|
|
if(window->getActiveTool()->getRenderer())
|
|
|
|
window->getActiveTool()->getRenderer()->render(window->getLevel(), rect, scale);
|
|
|
|
|
2007-10-23 19:08:04 +00:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopMatrix();
|
|
|
|
|
|
|
|
gdk_gl_drawable_swap_buffers(drawable);
|
|
|
|
gdk_gl_drawable_gl_end(drawable);
|
|
|
|
}
|
|
|
|
|
2007-12-24 00:04:02 +00:00
|
|
|
Drawer::Drawer(Window *window, GdkGLConfig *glconfig) : renderer(&window->getEditManager()) {
|
2007-10-04 23:38:05 +00:00
|
|
|
this->window = window;
|
|
|
|
zoomExp = 0;
|
2007-10-18 23:38:05 +00:00
|
|
|
scale = 100;
|
2007-11-16 01:29:04 +00:00
|
|
|
xCenter = 0;
|
|
|
|
yCenter = 0;
|
2007-10-04 23:38:05 +00:00
|
|
|
|
|
|
|
drawer = gtk_table_new(2, 2, FALSE);
|
|
|
|
g_object_ref_sink(G_OBJECT(drawer));
|
|
|
|
|
|
|
|
drawingArea = gtk_drawing_area_new();
|
|
|
|
gtk_widget_set_gl_capability(drawingArea, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
|
|
|
|
g_signal_connect(G_OBJECT(drawingArea), "realize", G_CALLBACK(realize), this);
|
|
|
|
g_signal_connect(G_OBJECT(drawingArea), "configure-event", G_CALLBACK(eventHandler), this);
|
|
|
|
g_signal_connect(G_OBJECT(drawingArea), "expose-event", G_CALLBACK(eventHandler), this);
|
|
|
|
g_signal_connect(G_OBJECT(drawingArea), "button-press-event", G_CALLBACK(eventHandler), this);
|
2007-12-25 03:27:03 +00:00
|
|
|
g_signal_connect(G_OBJECT(drawingArea), "button-release-event", G_CALLBACK(eventHandler), this);
|
2007-10-04 23:38:05 +00:00
|
|
|
g_signal_connect(G_OBJECT(drawingArea), "enter-notify-event", G_CALLBACK(eventHandler), this);
|
|
|
|
g_signal_connect(G_OBJECT(drawingArea), "leave-notify-event", G_CALLBACK(eventHandler), this);
|
|
|
|
g_signal_connect(G_OBJECT(drawingArea), "motion-notify-event", G_CALLBACK(eventHandler), this);
|
|
|
|
g_signal_connect(G_OBJECT(drawingArea), "scroll-event", G_CALLBACK(eventHandler), this);
|
2007-12-25 03:27:03 +00:00
|
|
|
gtk_widget_add_events(drawingArea, GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_RELEASE_MASK);
|
2007-10-04 23:38:05 +00:00
|
|
|
gtk_table_attach(GTK_TABLE(drawer), drawingArea, 0, 1, 0, 1, (GtkAttachOptions)(GTK_FILL|GTK_EXPAND|GTK_SHRINK), (GtkAttachOptions)(GTK_FILL|GTK_EXPAND|GTK_SHRINK), 0, 0);
|
|
|
|
|
|
|
|
hAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100));
|
|
|
|
GtkWidget *hScroll = gtk_hscrollbar_new(hAdjustment);
|
|
|
|
g_signal_connect(G_OBJECT(hScroll), "value-changed", G_CALLBACK(valueChanged), this);
|
|
|
|
gtk_table_attach(GTK_TABLE(drawer), hScroll, 0, 1, 1, 2, (GtkAttachOptions)(GTK_FILL|GTK_EXPAND|GTK_SHRINK), (GtkAttachOptions)0, 0, 0);
|
|
|
|
|
|
|
|
vAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100));
|
|
|
|
GtkWidget *vScroll = gtk_vscrollbar_new(vAdjustment);
|
|
|
|
g_signal_connect(G_OBJECT(vScroll), "value-changed", G_CALLBACK(valueChanged), this);
|
|
|
|
gtk_table_attach(GTK_TABLE(drawer), vScroll, 1, 2, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)(GTK_FILL|GTK_EXPAND|GTK_SHRINK), 0, 0);
|
|
|
|
|
|
|
|
gtk_widget_show_all(drawer);
|
|
|
|
}
|
|
|
|
|
|
|
|
Drawer::~Drawer() {
|
|
|
|
g_object_unref(G_OBJECT(drawer));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Drawer::zoom(int zoom, float x, float y) {
|
|
|
|
zoomExp = MAX(MIN(zoomExp + zoom, 50), -100);
|
|
|
|
|
2007-10-18 23:38:05 +00:00
|
|
|
scale = 100*powf(1.1f, zoomExp);
|
2007-10-04 23:38:05 +00:00
|
|
|
|
|
|
|
updateScrollbars(x, y);
|
|
|
|
}
|
2007-10-18 23:38:05 +00:00
|
|
|
|
2007-10-23 19:08:04 +00:00
|
|
|
void Drawer::imageToView(Vertex *v) const {
|
2007-11-16 01:29:04 +00:00
|
|
|
v->setX((v->getX()-xCenter)*scale + getWidth()/2);
|
|
|
|
v->setY((v->getY()-yCenter)*scale + getHeight()/2);
|
2007-10-18 23:38:05 +00:00
|
|
|
}
|
|
|
|
|
2007-10-23 19:08:04 +00:00
|
|
|
void Drawer::viewToImage(Vertex *v) const {
|
2007-11-16 01:29:04 +00:00
|
|
|
v->setX((v->getX()-getWidth()/2)/scale+xCenter);
|
|
|
|
v->setY((v->getY()-getHeight()/2)/scale+yCenter);
|
2007-10-18 23:38:05 +00:00
|
|
|
}
|
|
|
|
|
2007-10-23 19:08:04 +00:00
|
|
|
float Drawer::getImageWidth() const {
|
2007-11-16 17:49:00 +00:00
|
|
|
float max = 0;
|
2007-10-18 23:38:05 +00:00
|
|
|
|
2007-12-14 02:47:03 +00:00
|
|
|
for(Level::iterator object = window->getLevel().begin(); object != window->getLevel().end(); object++) {
|
|
|
|
if((*object)->isOfType("Room")) {
|
|
|
|
Room *room = (Room*)&**object;
|
|
|
|
|
|
|
|
for(Room::iterator v = room->begin(); v != room->end(); v++) {
|
|
|
|
max = fmaxf(max, fabsf(v->getX()));
|
|
|
|
}
|
2007-10-18 23:38:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-16 17:49:00 +00:00
|
|
|
return (2*max+1);
|
2007-10-18 23:38:05 +00:00
|
|
|
}
|
|
|
|
|
2007-10-23 19:08:04 +00:00
|
|
|
float Drawer::getImageHeight() const {
|
2007-11-16 17:49:00 +00:00
|
|
|
float max = 0;
|
2007-10-18 23:38:05 +00:00
|
|
|
|
2007-12-14 02:47:03 +00:00
|
|
|
for(Level::iterator object = window->getLevel().begin(); object != window->getLevel().end(); object++) {
|
|
|
|
if((*object)->isOfType("Room")) {
|
|
|
|
Room *room = (Room*)&**object;
|
|
|
|
|
|
|
|
for(Room::iterator v = room->begin(); v != room->end(); v++) {
|
|
|
|
max = fmaxf(max, fabsf(v->getY()));
|
|
|
|
}
|
2007-10-18 23:38:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-16 17:49:00 +00:00
|
|
|
return (2*max+1);
|
2007-10-18 23:38:05 +00:00
|
|
|
}
|