diff options
Diffstat (limited to 'src/displaywindow.c')
-rw-r--r-- | src/displaywindow.c | 231 |
1 files changed, 136 insertions, 95 deletions
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; } |