aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/displaywindow.ui2
-rw-r--r--src/displaywindow.c231
2 files changed, 138 insertions, 95 deletions
diff --git a/data/displaywindow.ui b/data/displaywindow.ui
index a5137fe..5255702 100644
--- a/data/displaywindow.ui
+++ b/data/displaywindow.ui
@@ -9,6 +9,8 @@
<menu name="view" action="ViewAction">
<menuitem name="ortho" action="OrthoAction" />
<menuitem name="perspective" action="PerspectiveAction" />
+ <separator />
+ <menuitem name="fog" action="FogAction" />
</menu>
<menu name="tools" action="ToolsAction">
diff --git a/src/displaywindow.c b/src/displaywindow.c
index 31889df..1d72f4f 100644
--- a/src/displaywindow.c
+++ b/src/displaywindow.c
@@ -34,28 +34,28 @@ enum {
DW_PERSPECTIVE
};
-GtkUIManager *displaywindow_ui;
-GtkActionGroup *displaywindow_action_group;
-GtkWidget *displaywindow_window;
-GtkWidget *displaywindow_bigvbox;
-GtkWidget *displaywindow_status_bar;
-int displaywindow_view = DW_ORTHO;
-GtkWidget *displaywindow_drawing_area;
-GLfloat displaywindow_distance = 150;
-GLfloat displaywindow_x_pos = 0;
-GLfloat displaywindow_y_pos = 0;
-
-void error_report(const char *message) {
-
- GtkWidget *window;
+typedef struct {
+
+ ControlContext *ctx;
+
+ GtkUIManager *ui;
+ GtkActionGroup *action_group;
+ GtkWidget *window;
+ GtkWidget *bigvbox;
+ GtkWidget *status_bar;
+ int view;
+ GtkWidget *drawing_area;
- window = gtk_message_dialog_new(GTK_WINDOW(displaywindow_window), GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, message);
-
- g_signal_connect_swapped(window, "response", G_CALLBACK(gtk_widget_destroy), window);
- gtk_widget_show(window);
+ /* OpenGL stuff */
+ GLfloat distance;
+ GLfloat x_pos;
+ GLfloat y_pos;
+ float x_start;
+ float y_start;
+ float view_quat[4];
+ int fog;
-}
+} DisplayWindow;
static void displaywindow_about() {
@@ -94,22 +94,22 @@ static void displaywindow_close() {
gtk_exit(0);
}
-static void displaywindow_gl_set_ortho(GLfloat w, GLfloat h) {
+static void displaywindow_gl_set_ortho(DisplayWindow *dw, GLfloat w, GLfloat h) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if ( w > h ) {
GLfloat aspect = w/h;
- glOrtho(-aspect*(displaywindow_distance/2), aspect*(displaywindow_distance/2), -(displaywindow_distance/2), (displaywindow_distance/2), 0.01, 1000.0);
+ glOrtho(-aspect*(dw->distance/2), aspect*(dw->distance/2), -(dw->distance/2), (dw->distance/2), 0.01, 1000.0);
} else {
GLfloat aspect = h/w;
- glOrtho(-(displaywindow_distance/2), (displaywindow_distance/2), -aspect*(displaywindow_distance/2), aspect*(displaywindow_distance/2), 0.01, 1000.0);
+ glOrtho(-(dw->distance/2), (dw->distance/2), -aspect*(dw->distance/2), aspect*(dw->distance/2), 0.01, 1000.0);
}
glMatrixMode(GL_MODELVIEW);
}
-static void displaywindow_gl_set_perspective(GLfloat w, GLfloat h) {
+static void displaywindow_gl_set_perspective(DisplayWindow *dw, GLfloat w, GLfloat h) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
@@ -124,22 +124,44 @@ static void displaywindow_gl_set_perspective(GLfloat w, GLfloat h) {
}
-static gint displaywindow_changeview(GtkWidget *widget, GtkRadioAction *action) {
+static gint displaywindow_changeview(GtkWidget *widget, GtkRadioAction *action, DisplayWindow *dw) {
- GLfloat w = displaywindow_drawing_area->allocation.width;
- GLfloat h = displaywindow_drawing_area->allocation.height;
- displaywindow_view = gtk_radio_action_get_current_value(action);
+ GLfloat w = dw->drawing_area->allocation.width;
+ GLfloat h = dw->drawing_area->allocation.height;
+ dw->view = gtk_radio_action_get_current_value(action);
- if ( displaywindow_view == DW_ORTHO ) {
- displaywindow_gl_set_ortho(w, h);
+ if ( dw->view == DW_ORTHO ) {
+ displaywindow_gl_set_ortho(dw, w, h);
} else {
- displaywindow_gl_set_perspective(w, h);
+ displaywindow_gl_set_perspective(dw, w, h);
}
return 0;
}
+static gint displaywindow_changefog(GtkWidget *widget, DisplayWindow *dw) {
+
+ GdkGLContext *glcontext;
+ GdkGLDrawable *gldrawable;
+
+ glcontext = gtk_widget_get_gl_context(dw->drawing_area);
+ gldrawable = gtk_widget_get_gl_drawable(dw->drawing_area);
+
+ dw->fog = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(widget));
+ if ( !gdk_gl_drawable_gl_begin(gldrawable, glcontext) ) {
+ return 1;
+ }
+ if ( dw->fog ) {
+ glEnable(GL_FOG);
+ } else {
+ glDisable(GL_FOG);
+ }
+ gdk_gl_drawable_gl_end(gldrawable);
+
+ return 0;
+}
+
static void displaywindow_addui_callback(GtkUIManager *ui, GtkWidget *widget, GtkContainer *container) {
gtk_box_pack_start(GTK_BOX(container), widget, FALSE, FALSE, 0);
@@ -151,7 +173,7 @@ static void displaywindow_addui_callback(GtkUIManager *ui, GtkWidget *widget, Gt
}
-static void displaywindow_addmenubar() {
+static void displaywindow_addmenubar(DisplayWindow *dw) {
GtkActionEntry entries[] = {
@@ -168,43 +190,43 @@ static void displaywindow_addmenubar() {
};
guint n_entries = G_N_ELEMENTS(entries);
- GtkRadioActionEntry toggles[] = {
+ GtkRadioActionEntry radios[] = {
{ "OrthoAction", NULL, "_Orthographic", NULL, NULL, DW_ORTHO },
{ "PerspectiveAction", NULL, "_Perspective", NULL, NULL, DW_PERSPECTIVE },
};
+ guint n_radios = G_N_ELEMENTS(radios);
+ GtkToggleActionEntry toggles[] = {
+ { "FogAction", NULL, "_Fog", NULL, NULL, G_CALLBACK(displaywindow_changefog), FALSE },
+ };
guint n_toggles = G_N_ELEMENTS(toggles);
GError *error = NULL;
- displaywindow_action_group = gtk_action_group_new("dtrdisplaywindow");
- gtk_action_group_add_actions(displaywindow_action_group, entries, n_entries, displaywindow_window);
- gtk_action_group_add_radio_actions(displaywindow_action_group, toggles, n_toggles, -1, G_CALLBACK(displaywindow_changeview), NULL);
+ dw->action_group = gtk_action_group_new("dtrdisplaywindow");
+ gtk_action_group_add_actions(dw->action_group, entries, n_entries, dw);
+ gtk_action_group_add_radio_actions(dw->action_group, radios, n_radios, -1, G_CALLBACK(displaywindow_changeview), dw);
+ gtk_action_group_add_toggle_actions(dw->action_group, toggles, n_toggles, dw);
- displaywindow_ui = gtk_ui_manager_new();
- gtk_ui_manager_insert_action_group(displaywindow_ui, displaywindow_action_group, 0);
- g_signal_connect(displaywindow_ui, "add_widget", G_CALLBACK(displaywindow_addui_callback), displaywindow_bigvbox);
- if ( gtk_ui_manager_add_ui_from_file(displaywindow_ui, DATADIR"/dtr/displaywindow.ui", &error) == 0 ) {
+ dw->ui = gtk_ui_manager_new();
+ gtk_ui_manager_insert_action_group(dw->ui, dw->action_group, 0);
+ g_signal_connect(dw->ui, "add_widget", G_CALLBACK(displaywindow_addui_callback), dw->bigvbox);
+ if ( gtk_ui_manager_add_ui_from_file(dw->ui, DATADIR"/dtr/displaywindow.ui", &error) == 0 ) {
fprintf(stderr, "Error loading message window menu bar: %s\n", error->message);
return;
}
- gtk_window_add_accel_group(GTK_WINDOW(displaywindow_window), gtk_ui_manager_get_accel_group(displaywindow_ui));
- gtk_ui_manager_ensure_update(displaywindow_ui);
+ gtk_window_add_accel_group(GTK_WINDOW(dw->window), gtk_ui_manager_get_accel_group(dw->ui));
+ gtk_ui_manager_ensure_update(dw->ui);
}
-static float displaywindow_x_start = 0.0;
-static float displaywindow_y_start = 0.0;
-
-static float view_quat[4] = { 0.0, 0.0, 0.0, 1.0 };
-
-static gboolean displaywindow_gl_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) {
- displaywindow_x_start = event->x;
- displaywindow_y_start = event->y;
+static gboolean displaywindow_gl_button_press(GtkWidget *widget, GdkEventButton *event, DisplayWindow *dw) {
+ dw->x_start = event->x;
+ dw->y_start = event->y;
return FALSE;
}
-static gint displaywindow_gl_motion_notify(GtkWidget *widget, GdkEventMotion *event, gpointer data) {
+static gint displaywindow_gl_motion_notify(GtkWidget *widget, GdkEventMotion *event, DisplayWindow *dw) {
float w = widget->allocation.width;
float h = widget->allocation.height;
@@ -215,30 +237,31 @@ static gint displaywindow_gl_motion_notify(GtkWidget *widget, GdkEventMotion *ev
if ( event->state & GDK_CONTROL_MASK ) {
/* Control-click changes 'zoom' */
- displaywindow_distance += event->y - displaywindow_y_start;
- if ( displaywindow_view == DW_ORTHO ) {
- displaywindow_gl_set_ortho(w, h);
+ dw->distance += event->y - dw->y_start;
+ if ( dw->view == DW_ORTHO ) {
+ displaywindow_gl_set_ortho(dw, w, h);
}
} else if ( event->state & GDK_SHIFT_MASK ) {
/* Shift-click translates */
- displaywindow_x_pos += (event->x - displaywindow_x_start)/5;
- displaywindow_y_pos += (event->y - displaywindow_y_start)/5;
+ dw->x_pos += (event->x - dw->x_start)/5;
+ dw->y_pos += (event->y - dw->y_start)/5;
} else {
/* Click rotates */
- trackball(d_quat, (2.0*displaywindow_x_start - w)/w, (h-2.0*displaywindow_y_start)/h, (2.0*x-w)/w, (h-2.0*y)/h);
- add_quats(d_quat, view_quat, view_quat);
+ trackball(d_quat, (2.0*dw->x_start - w)/w, (h-2.0*dw->y_start)/h, (2.0*x-w)/w, (h-2.0*y)/h);
+ add_quats(d_quat, dw->view_quat, dw->view_quat);
}
- displaywindow_x_start = x;
- displaywindow_y_start = y;
+ dw->x_start = x;
+ dw->y_start = y;
gdk_window_invalidate_rect(widget->window, &widget->allocation, FALSE);
return TRUE;
+
}
#define BLOB_BITS 5
@@ -563,7 +586,7 @@ static void displaywindow_gl_create_list(ControlContext *ctx) {
}
-static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, ControlContext *ctx) {
+static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, DisplayWindow *dw) {
GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
@@ -579,6 +602,7 @@ static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, Co
GLfloat light1_position[] = { 0.0, 0.0, -100.0, 0.0 };
GLfloat light1_diffuse[] = { 0.8, 0.8, 0.8, 1.0 };
GLfloat light1_specular[] = { 0.5, 0.5, 0.5, 1.0 };
+ ControlContext *ctx = dw->ctx;
if ( !gdk_gl_drawable_gl_begin(gldrawable, glcontext) ) {
return 0;
@@ -587,8 +611,8 @@ static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, Co
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity();
- glTranslatef(displaywindow_x_pos, -displaywindow_y_pos, -displaywindow_distance);
- build_rotmatrix(m, view_quat);
+ glTranslatef(dw->x_pos, -dw->y_pos, -dw->distance);
+ build_rotmatrix(m, dw->view_quat);
glMultMatrixf(&m[0][0]);
/* Set up lighting */
@@ -675,18 +699,19 @@ static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, Co
}
-static gint displaywindow_gl_realise(GtkWidget *widget, ControlContext *ctx) {
+static gint displaywindow_gl_realise(GtkWidget *widget, DisplayWindow *dw) {
GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
GLfloat w = widget->allocation.width;
GLfloat h = widget->allocation.height;
+ ControlContext *ctx = dw->ctx;
if ( !gdk_gl_drawable_gl_begin(gldrawable, glcontext) ) {
return 0;
}
- displaywindow_gl_set_ortho(w, h);
+ displaywindow_gl_set_ortho(dw, w, h);
displaywindow_gl_create_list(ctx);
gdk_gl_drawable_gl_end(gldrawable);
@@ -695,7 +720,7 @@ static gint displaywindow_gl_realise(GtkWidget *widget, ControlContext *ctx) {
}
-static gboolean displaywindow_gl_configure(GtkWidget *widget, GdkEventConfigure *event, gpointer data) {
+static gboolean displaywindow_gl_configure(GtkWidget *widget, GdkEventConfigure *event, DisplayWindow *dw) {
GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
@@ -709,17 +734,17 @@ static gboolean displaywindow_gl_configure(GtkWidget *widget, GdkEventConfigure
glViewport(0, 0, w, h);
glEnable(GL_DEPTH_TEST);
- glEnable(GL_FOG);
+ if ( dw->fog ) glEnable(GL_FOG);
glFogf(GL_FOG_DENSITY, 0.005);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel(GL_SMOOTH);
/* Nudge the projection matrix routines to preserve the aspect ratio */
- if ( displaywindow_view == DW_ORTHO ) {
- displaywindow_gl_set_ortho(w, h);
+ if ( dw->view == DW_ORTHO ) {
+ displaywindow_gl_set_ortho(dw, w, h);
} else {
- displaywindow_gl_set_perspective(w, h);
+ displaywindow_gl_set_perspective(dw, w, h);
}
gdk_gl_drawable_gl_end(gldrawable);
@@ -728,17 +753,20 @@ static gboolean displaywindow_gl_configure(GtkWidget *widget, GdkEventConfigure
}
-static gint displaywindow_closedown(GtkWidget *widget, gpointer data) {
+static gint displaywindow_closedown(GtkWidget *widget, DisplayWindow *dw) {
return 0;
}
-void displaywindow_open(ControlContext *ctx) {
+DisplayWindow *displaywindow_open(ControlContext *ctx) {
const char *filename;
char *title;
GdkGLConfig *glconfig;
+ DisplayWindow *dw;
+
+ dw = malloc(sizeof(DisplayWindow));
filename = basename(ctx->filename);
title = malloc(10+strlen(filename));
@@ -747,19 +775,30 @@ void displaywindow_open(ControlContext *ctx) {
ctx->gl_use_buffers = 1;
- displaywindow_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(displaywindow_window), title);
+ dw->view = DW_ORTHO;
+ dw->distance = 150;
+ dw->x_pos = 0;
+ dw->y_pos = 0;
+ dw->view_quat[0] = 0.0;
+ dw->view_quat[1] = 0.0;
+ dw->view_quat[2] = 0.0;
+ dw->view_quat[3] = 1.0;
+ dw->ctx = ctx;
+ dw->fog = 0;
+
+ dw->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(dw->window), title);
free(title);
- displaywindow_bigvbox = gtk_vbox_new(FALSE, FALSE);
- gtk_container_add(GTK_CONTAINER(displaywindow_window), displaywindow_bigvbox);
- displaywindow_addmenubar();
+ dw->bigvbox = gtk_vbox_new(FALSE, FALSE);
+ gtk_container_add(GTK_CONTAINER(dw->window), dw->bigvbox);
+ displaywindow_addmenubar(dw);
- displaywindow_status_bar = gtk_statusbar_new();
- gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(displaywindow_status_bar), FALSE);
- gtk_box_pack_end(GTK_BOX(displaywindow_bigvbox), displaywindow_status_bar, FALSE, FALSE, 0);
+ dw->status_bar = gtk_statusbar_new();
+ gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(dw->status_bar), FALSE);
+ gtk_box_pack_end(GTK_BOX(dw->bigvbox), dw->status_bar, FALSE, FALSE, 0);
- g_signal_connect(GTK_OBJECT(displaywindow_window), "destroy", G_CALLBACK(displaywindow_closedown), NULL);
- g_signal_connect_after(GTK_OBJECT(displaywindow_window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
+ g_signal_connect(GTK_OBJECT(dw->window), "destroy", G_CALLBACK(displaywindow_closedown), NULL);
+ g_signal_connect_after(GTK_OBJECT(dw->window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
/* GL stuff */
glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE);
@@ -767,19 +806,21 @@ void displaywindow_open(ControlContext *ctx) {
fprintf(stderr, "Can't find double-buffered visual.\n");
exit(1);
}
- gtk_container_set_reallocate_redraws(GTK_CONTAINER(displaywindow_window), TRUE);
- displaywindow_drawing_area = gtk_drawing_area_new();
- gtk_widget_set_size_request(displaywindow_drawing_area, 640, 640);
- gtk_widget_set_gl_capability(displaywindow_drawing_area, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
- gtk_box_pack_start(GTK_BOX(displaywindow_bigvbox), displaywindow_drawing_area, TRUE, TRUE, 0);
- gtk_widget_add_events(displaywindow_drawing_area, GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_VISIBILITY_NOTIFY_MASK);
- g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "configure_event", G_CALLBACK(displaywindow_gl_configure), NULL);
- g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "realize", G_CALLBACK(displaywindow_gl_realise), ctx);
- g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "expose_event", G_CALLBACK(displaywindow_gl_expose), ctx);
- g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "button_press_event", G_CALLBACK(displaywindow_gl_button_press), NULL);
- g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "motion_notify_event", G_CALLBACK(displaywindow_gl_motion_notify), NULL);
-
- gtk_widget_show_all(displaywindow_window);
+ gtk_container_set_reallocate_redraws(GTK_CONTAINER(dw->window), TRUE);
+ dw->drawing_area = gtk_drawing_area_new();
+ gtk_widget_set_size_request(dw->drawing_area, 640, 640);
+ gtk_widget_set_gl_capability(dw->drawing_area, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
+ gtk_box_pack_start(GTK_BOX(dw->bigvbox), dw->drawing_area, TRUE, TRUE, 0);
+ gtk_widget_add_events(dw->drawing_area, GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_VISIBILITY_NOTIFY_MASK);
+ g_signal_connect(GTK_OBJECT(dw->drawing_area), "configure_event", G_CALLBACK(displaywindow_gl_configure), dw);
+ g_signal_connect(GTK_OBJECT(dw->drawing_area), "realize", G_CALLBACK(displaywindow_gl_realise), dw);
+ g_signal_connect(GTK_OBJECT(dw->drawing_area), "expose_event", G_CALLBACK(displaywindow_gl_expose), dw);
+ g_signal_connect(GTK_OBJECT(dw->drawing_area), "button_press_event", G_CALLBACK(displaywindow_gl_button_press), dw);
+ g_signal_connect(GTK_OBJECT(dw->drawing_area), "motion_notify_event", G_CALLBACK(displaywindow_gl_motion_notify), dw);
+
+ gtk_widget_show_all(dw->window);
+
+ return dw;
}