From 5e8bf923bce829075eb0754eecfd7e6b9b768a61 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Tue, 4 Aug 2009 06:22:49 +0000 Subject: [PATCH] Refactoring a lot of things. Taking all the opengl and GIS stuff out of AWeather and putting it in a Gis prefix. --- src/Makefile.am | 4 +- src/aweather-gui.c | 365 ++++++++++++------------------------------- src/aweather-gui.h | 23 +-- src/aweather-view.c | 349 ----------------------------------------- src/aweather-view.h | 77 --------- src/gis-opengl.c | 270 ++++++++++++++++++++++++++++++++ src/gis-opengl.h | 66 ++++++++ src/gis-view.c | 295 ++++++++++++++++++++++++++++++++++ src/gis-view.h | 71 +++++++++ src/gis-world.c | 123 +++++++++++++++ src/gis-world.h | 57 +++++++ src/location.h | 4 +- src/main.c | 15 +- src/plugin-example.c | 10 +- src/plugin-radar.c | 44 +++--- src/plugin-ridge.c | 25 +-- 16 files changed, 1055 insertions(+), 743 deletions(-) delete mode 100644 src/aweather-view.c delete mode 100644 src/aweather-view.h create mode 100644 src/gis-opengl.c create mode 100644 src/gis-opengl.h create mode 100644 src/gis-view.c create mode 100644 src/gis-view.h create mode 100644 src/gis-world.c create mode 100644 src/gis-world.h diff --git a/src/Makefile.am b/src/Makefile.am index 620cdcb..1c00635 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,8 +6,10 @@ BUILT_SOURCES = marshal.c marshal.h aweather_SOURCES = main.c \ marshal.c marshal.h \ aweather-gui.c aweather-gui.h \ - aweather-view.c aweather-view.h \ aweather-plugin.c aweather-plugin.h \ + gis-opengl.c gis-opengl.h \ + gis-view.c gis-view.h \ + gis-world.c gis-world.h \ data.c data.h \ location.c location.h \ marching.c marching.h \ diff --git a/src/aweather-gui.c b/src/aweather-gui.c index da4c161..47bc4f2 100644 --- a/src/aweather-gui.c +++ b/src/aweather-gui.c @@ -17,25 +17,26 @@ #include #include -#include #include -#include -#include #include #include "misc.h" #include "aweather-gui.h" -#include "aweather-view.h" #include "aweather-plugin.h" +#include "gis-opengl.h" #include "location.h" /**************** * GObject code * ****************/ G_DEFINE_TYPE(AWeatherGui, aweather_gui, GTK_TYPE_WINDOW); -static void aweather_gui_init(AWeatherGui *gui) +static void aweather_gui_init(AWeatherGui *self) { - gui->plugins = NULL; + self->world = NULL; + self->view = NULL; + self->opengl = NULL; + self->builder = NULL; + self->plugins = NULL; g_debug("AWeatherGui: init"); } static GObject *aweather_gui_constructor(GType gtype, guint n_properties, @@ -45,35 +46,41 @@ static GObject *aweather_gui_constructor(GType gtype, guint n_properties, GObjectClass *parent_class = G_OBJECT_CLASS(aweather_gui_parent_class); return parent_class->constructor(gtype, n_properties, properties); } -static void aweather_gui_dispose(GObject *gobject) +static void aweather_gui_dispose(GObject *_self) { g_debug("AWeatherGui: dispose"); - AWeatherGui *gui = AWEATHER_GUI(gobject); - if (gui->view) { - g_object_unref(gui->view); - gui->view = NULL; + AWeatherGui *self = AWEATHER_GUI(_self); + if (self->world) { + g_object_unref(self->world); + self->world = NULL; } - if (gui->builder) { + if (self->view) { + g_object_unref(self->view); + self->view = NULL; + } + if (self->opengl) { + g_object_unref(self->opengl); + self->opengl = NULL; + } + if (self->builder) { /* Reparent to avoid double unrefs */ - GtkWidget *body = aweather_gui_get_widget(gui, "body"); - GtkWidget *window = aweather_gui_get_widget(gui, "window"); + GtkWidget *body = aweather_gui_get_widget(self, "body"); + GtkWidget *window = aweather_gui_get_widget(self, "window"); gtk_widget_reparent(body, window); - g_object_unref(gui->builder); - gui->builder = NULL; + g_object_unref(self->builder); + self->builder = NULL; } - if (gui->plugins) { - g_list_foreach(gui->plugins, (GFunc)g_object_unref, NULL); - g_list_free(gui->plugins); - gui->plugins = NULL; + if (self->plugins) { + g_list_foreach(self->plugins, (GFunc)g_object_unref, NULL); + g_list_free(self->plugins); + self->plugins = NULL; } - //for (GList *cur = gui->plugins; cur; cur = cur->next) - // g_object_unref(cur->data); - G_OBJECT_CLASS(aweather_gui_parent_class)->dispose(gobject); + G_OBJECT_CLASS(aweather_gui_parent_class)->dispose(_self); } -static void aweather_gui_finalize(GObject *gobject) +static void aweather_gui_finalize(GObject *_self) { g_debug("AWeatherGui: finalize"); - G_OBJECT_CLASS(aweather_gui_parent_class)->finalize(gobject); + G_OBJECT_CLASS(aweather_gui_parent_class)->finalize(_self); gtk_main_quit(); } @@ -89,45 +96,16 @@ static void aweather_gui_class_init(AWeatherGuiClass *klass) /************* * Callbacks * *************/ -gboolean on_drawing_button_press(GtkWidget *widget, GdkEventButton *event, AWeatherGui *gui) -{ - g_debug("AWeatherGui: on_drawing_button_press - Grabbing focus"); - GtkWidget *drawing = aweather_gui_get_widget(gui, "drawing"); - gtk_widget_grab_focus(drawing); - return TRUE; -} -gboolean on_drawing_key_press(GtkWidget *widget, GdkEventKey *event, AWeatherGui *gui) -{ - g_debug("AWeatherGui: on_drawing_key_press - key=%x, state=%x, plus=%x", - event->keyval, event->state, GDK_plus); - AWeatherView *view = aweather_gui_get_view(gui); - double x,y,z; - aweather_view_get_location(view, &x, &y, &z); - guint kv = event->keyval; - if (kv == GDK_Left || kv == GDK_h) aweather_view_pan(view, -z/10, 0, 0); - else if (kv == GDK_Down || kv == GDK_j) aweather_view_pan(view, 0, -z/10, 0); - else if (kv == GDK_Up || kv == GDK_k) aweather_view_pan(view, 0, z/10, 0); - else if (kv == GDK_Right || kv == GDK_l) aweather_view_pan(view, z/10, 0, 0); - else if (kv == GDK_minus || kv == GDK_o) aweather_view_zoom(view, 10./9); - else if (kv == GDK_plus || kv == GDK_i) aweather_view_zoom(view, 9./10); - else if (kv == GDK_H ) aweather_view_rotate(view, 0, -10, 0); - else if (kv == GDK_J ) aweather_view_rotate(view, 10, 0, 0); - else if (kv == GDK_K ) aweather_view_rotate(view, -10, 0, 0); - else if (kv == GDK_L ) aweather_view_rotate(view, 0, 10, 0); - return TRUE; -} - -gboolean on_gui_key_press(GtkWidget *widget, GdkEventKey *event, AWeatherGui *gui) +gboolean on_gui_key_press(GtkWidget *widget, GdkEventKey *event, AWeatherGui *self) { g_debug("AWeatherGui: on_gui_key_press - key=%x, state=%x", event->keyval, event->state); - AWeatherView *view = aweather_gui_get_view(gui); if (event->keyval == GDK_q) - gtk_widget_destroy(GTK_WIDGET(gui)); + gtk_widget_destroy(GTK_WIDGET(self)); else if (event->keyval == GDK_r && event->state & GDK_CONTROL_MASK) - aweather_view_refresh(view); + gis_world_refresh(self->world); else if (event->keyval == GDK_Tab || event->keyval == GDK_ISO_Left_Tab) { - GtkNotebook *tabs = GTK_NOTEBOOK(aweather_gui_get_widget(gui, "tabs")); + GtkNotebook *tabs = GTK_NOTEBOOK(aweather_gui_get_widget(self, "tabs")); gint num_tabs = gtk_notebook_get_n_pages(tabs); gint cur_tab = gtk_notebook_get_current_page(tabs); if (event->state & GDK_SHIFT_MASK) @@ -138,37 +116,33 @@ gboolean on_gui_key_press(GtkWidget *widget, GdkEventKey *event, AWeatherGui *gu return FALSE; } -void on_quit(GtkMenuItem *menu, AWeatherGui *gui) +void on_quit(GtkMenuItem *menu, AWeatherGui *self) { - gtk_widget_destroy(GTK_WIDGET(gui)); + gtk_widget_destroy(GTK_WIDGET(self)); } -void on_offline(GtkToggleAction *action, AWeatherGui *gui) +void on_offline(GtkToggleAction *action, AWeatherGui *self) { - AWeatherView *view = aweather_gui_get_view(gui); - aweather_view_set_offline(view, + gis_world_set_offline(self->world, gtk_toggle_action_get_active(action)); } -void on_zoomin(GtkAction *action, AWeatherGui *gui) +void on_zoomin(GtkAction *action, AWeatherGui *self) { - AWeatherView *view = aweather_gui_get_view(gui); - aweather_view_zoom(view, 3./4); + gis_view_zoom(self->view, 3./4); } -void on_zoomout(GtkAction *action, AWeatherGui *gui) +void on_zoomout(GtkAction *action, AWeatherGui *self) { - AWeatherView *view = aweather_gui_get_view(gui); - aweather_view_zoom(view, 4./3); + gis_view_zoom(self->view, 4./3); } -void on_refresh(GtkAction *action, AWeatherGui *gui) +void on_refresh(GtkAction *action, AWeatherGui *self) { - AWeatherView *view = aweather_gui_get_view(gui); - aweather_view_refresh(view); + gis_world_refresh(self->world); } -void on_about(GtkAction *action, AWeatherGui *gui) +void on_about(GtkAction *action, AWeatherGui *self) { // TODO: use gtk_widget_hide_on_delete() GError *error = NULL; @@ -178,132 +152,39 @@ void on_about(GtkAction *action, AWeatherGui *gui) gtk_builder_connect_signals(builder, NULL); GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); gtk_window_set_transient_for(GTK_WINDOW(window), - GTK_WINDOW(aweather_gui_get_widget(gui, "window"))); + GTK_WINDOW(aweather_gui_get_widget(self, "window"))); gtk_widget_show_all(window); g_object_unref(builder); } void on_time_changed(GtkTreeView *view, GtkTreePath *path, - GtkTreeViewColumn *column, AWeatherGui *gui) + GtkTreeViewColumn *column, AWeatherGui *self) { gchar *time; GtkTreeIter iter; GtkTreeModel *model = gtk_tree_view_get_model(view); gtk_tree_model_get_iter(model, &iter, path); gtk_tree_model_get(model, &iter, 0, &time, -1); - AWeatherView *aview = aweather_gui_get_view(gui); - aweather_view_set_time(aview, time); + gis_view_set_time(self->view, time); g_free(time); } -void on_site_changed(GtkComboBox *combo, AWeatherGui *gui) +void on_site_changed(GtkComboBox *combo, AWeatherGui *self) { gchar *site; GtkTreeIter iter; GtkTreeModel *model = gtk_combo_box_get_model(combo); gtk_combo_box_get_active_iter(combo, &iter); gtk_tree_model_get(model, &iter, 1, &site, -1); - AWeatherView *view = aweather_gui_get_view(gui); - aweather_view_set_site(view, site); + gis_view_set_site(self->view, site); g_free(site); } -gboolean on_map(GtkWidget *da, GdkEventConfigure *event, AWeatherGui *gui) -{ - g_debug("AWeatherGui: on_map"); - AWeatherView *view = aweather_gui_get_view(gui); - - /* Misc */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - - /* Tessellation, "finding intersecting triangles" */ - /* http://research.microsoft.com/pubs/70307/tr-2006-81.pdf */ - /* http://www.opengl.org/wiki/Alpha_Blending */ - glAlphaFunc(GL_GREATER,0.1); - glEnable(GL_ALPHA_TEST); - - /* Depth test */ - glClearDepth(1.0); - glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); - - aweather_gui_gl_end(gui); - return FALSE; -} - -gboolean on_configure(GtkWidget *da, GdkEventConfigure *event, AWeatherGui *gui) -{ - g_debug("AWeatherGui: on_confiure"); - aweather_gui_gl_begin(gui); - - double x, y, z; - AWeatherView *view = aweather_gui_get_view(gui); - aweather_view_get_location(view, &x, &y, &z); - - /* Window is at 500 m from camera */ - double width = da->allocation.width; - double height = da->allocation.height; - - glViewport(0, 0, width, height); - - /* Perspective */ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - double ang = atan((height/2)/500); - - //gluPerspective(r2d(ang)*2, width/height, -z-20, -z+20); - gluPerspective(r2d(ang)*2, width/height, 1, 500*1000); - - aweather_gui_gl_end(gui); - return FALSE; -} - -gboolean on_expose(GtkWidget *da, GdkEventExpose *event, AWeatherGui *gui) -{ - g_debug("AWeatherGui: on_expose - begin"); - aweather_gui_gl_begin(gui); - - double lx, ly, lz; - double rx, ry, rz; - AWeatherView *view = aweather_gui_get_view(gui); - aweather_view_get_location(view, &lx, &ly, &lz); - aweather_view_get_rotation(view, &rx, &ry, &rz); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(lx, ly, lz); - glRotatef(rx, 1, 0, 0); - glRotatef(ry, 0, 1, 0); - glRotatef(rz, 0, 0, 1); - - /* Expose plugins */ - for (GList *cur = gui->plugins; cur; cur = cur->next) { - AWeatherPlugin *plugin = AWEATHER_PLUGIN(cur->data); - aweather_plugin_expose(plugin); - } - - aweather_gui_gl_end(gui); - aweather_gui_gl_flush(gui); - g_debug("AWeatherGui: on_expose - end\n"); - return FALSE; -} - -void on_state_changed(AWeatherView *view, - gdouble x, gdouble y, gdouble z, AWeatherGui *gui) -{ - /* Reset clipping area and redraw */ - GtkWidget *da = aweather_gui_get_widget(gui, "drawing"); - on_configure(da, NULL, gui); - aweather_gui_gl_redraw(gui); -} - /* TODO: replace the code in these with `gtk_tree_model_find' utility */ -static void update_time_widget(AWeatherView *view, const char *time, AWeatherGui *gui) +static void update_time_widget(GisView *view, const char *time, AWeatherGui *self) { g_debug("AWeatherGui: update_time_widget - time=%s", time); - GtkTreeView *tview = GTK_TREE_VIEW(aweather_gui_get_widget(gui, "time")); + GtkTreeView *tview = GTK_TREE_VIEW(aweather_gui_get_widget(self, "time")); GtkTreeModel *model = GTK_TREE_MODEL(gtk_tree_view_get_model(tview)); for (int i = 0; i < gtk_tree_model_iter_n_children(model, NULL); i++) { char *text; @@ -313,10 +194,10 @@ static void update_time_widget(AWeatherView *view, const char *time, AWeatherGui if (g_str_equal(text, time)) { GtkTreePath *path = gtk_tree_model_get_path(model, &iter); g_signal_handlers_block_by_func(tview, - G_CALLBACK(on_site_changed), gui); + G_CALLBACK(on_site_changed), self); gtk_tree_view_set_cursor(tview, path, NULL, FALSE); g_signal_handlers_unblock_by_func(tview, - G_CALLBACK(on_site_changed), gui); + G_CALLBACK(on_site_changed), self); gtk_tree_path_free(path); g_free(text); return; @@ -324,10 +205,10 @@ static void update_time_widget(AWeatherView *view, const char *time, AWeatherGui g_free(text); } } -static void update_site_widget(AWeatherView *view, char *site, AWeatherGui *gui) +static void update_site_widget(GisView *view, char *site, AWeatherGui *self) { g_debug("AWeatherGui: updat_site_widget - site=%s", site); - GtkComboBox *combo = GTK_COMBO_BOX(aweather_gui_get_widget(gui, "site")); + GtkComboBox *combo = GTK_COMBO_BOX(aweather_gui_get_widget(self, "site")); GtkTreeModel *model = GTK_TREE_MODEL(gtk_combo_box_get_model(combo)); for (int i = 0; i < gtk_tree_model_iter_n_children(model, NULL); i++) { GtkTreeIter iter1; @@ -341,10 +222,10 @@ static void update_site_widget(AWeatherView *view, char *site, AWeatherGui *gui) continue; if (g_str_equal(text, site)) { g_signal_handlers_block_by_func(combo, - G_CALLBACK(on_site_changed), gui); + G_CALLBACK(on_site_changed), self); gtk_combo_box_set_active_iter(combo, &iter2); g_signal_handlers_unblock_by_func(combo, - G_CALLBACK(on_site_changed), gui); + G_CALLBACK(on_site_changed), self); g_free(text); return; } @@ -363,10 +244,10 @@ static void combo_sensitive(GtkCellLayout *cell_layout, GtkCellRenderer *cell, g_object_set(cell, "sensitive", sensitive, NULL); } -static void site_setup(AWeatherGui *gui) +static void site_setup(AWeatherGui *self) { GtkTreeIter state, city; - GtkTreeStore *store = GTK_TREE_STORE(aweather_gui_get_object(gui, "sites")); + GtkTreeStore *store = GTK_TREE_STORE(aweather_gui_get_object(self, "sites")); for (int i = 0; cities[i].label; i++) { if (cities[i].type == LOCATION_STATE) { gtk_tree_store_append(store, &state, NULL); @@ -379,18 +260,18 @@ static void site_setup(AWeatherGui *gui) } } - GtkWidget *combo = aweather_gui_get_widget(gui, "site"); - GObject *renderer = aweather_gui_get_object(gui, "site_rend"); + GtkWidget *combo = aweather_gui_get_widget(self, "site"); + GObject *renderer = aweather_gui_get_object(self, "site_rend"); gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(combo), GTK_CELL_RENDERER(renderer), combo_sensitive, NULL, NULL); - AWeatherView *aview = aweather_gui_get_view(gui); - g_signal_connect(aview, "site-changed", G_CALLBACK(update_site_widget), gui); + g_signal_connect(self->view, "site-changed", + G_CALLBACK(update_site_widget), self); } -static void time_setup(AWeatherGui *gui) +static void time_setup(AWeatherGui *self) { - GtkTreeView *tview = GTK_TREE_VIEW(aweather_gui_get_widget(gui, "time")); + GtkTreeView *tview = GTK_TREE_VIEW(aweather_gui_get_widget(self, "time")); GtkCellRenderer *rend = gtk_cell_renderer_text_new(); GtkTreeViewColumn *col = gtk_tree_view_column_new_with_attributes( "Time", rend, "text", 0, NULL); @@ -398,27 +279,8 @@ static void time_setup(AWeatherGui *gui) gtk_tree_view_append_column(tview, col); g_object_set(rend, "size-points", 8.0, NULL); - AWeatherView *aview = aweather_gui_get_view(gui); - g_signal_connect(aview, "time-changed", G_CALLBACK(update_time_widget), gui); -} - -static void opengl_setup(AWeatherGui *gui) -{ - GtkDrawingArea *drawing = GTK_DRAWING_AREA(aweather_gui_get_widget(gui, "drawing")); - - GdkGLConfig *glconfig = gdk_gl_config_new_by_mode( - GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH | - GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA); - if (!glconfig) - g_error("Failed to create glconfig"); - if (!gtk_widget_set_gl_capability(GTK_WIDGET(drawing), - glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE)) - g_error("GL lacks required capabilities"); - - /* Set up OpenGL Stuff, glade doesn't like doing these */ - g_signal_connect(drawing, "map-event", G_CALLBACK(on_map), gui); - g_signal_connect(drawing, "configure-event", G_CALLBACK(on_configure), gui); - g_signal_connect(drawing, "expose-event", G_CALLBACK(on_expose), gui); + g_signal_connect(self->view, "time-changed", + G_CALLBACK(update_time_widget), self); } @@ -432,94 +294,69 @@ AWeatherGui *aweather_gui_new() GError *error = NULL; AWeatherGui *self = g_object_new(AWEATHER_TYPE_GUI, NULL); - self->view = aweather_view_new(); self->builder = gtk_builder_new(); if (!gtk_builder_add_from_file(self->builder, DATADIR "/aweather/main.ui", &error)) g_error("Failed to create gtk builder: %s", error->message); gtk_widget_reparent(aweather_gui_get_widget(self, "body"), GTK_WIDGET(self)); + GtkWidget *drawing = aweather_gui_get_widget(self, "drawing"); + g_debug("drawing=%p", drawing); + self->world = gis_world_new(); + self->view = gis_view_new(); + self->opengl = gis_opengl_new(self->world, self->view, GTK_DRAWING_AREA(drawing)); + /* Connect signals */ gtk_builder_connect_signals(self->builder, self); g_signal_connect(self, "key-press-event", G_CALLBACK(on_gui_key_press), self); - g_signal_connect(self->view, "location-changed", - G_CALLBACK(on_state_changed), self); - g_signal_connect(self->view, "rotation-changed", - G_CALLBACK(on_state_changed), self); - g_signal_connect_swapped(self->view, "offline", + g_signal_connect_swapped(self->world, "offline", G_CALLBACK(gtk_toggle_action_set_active), aweather_gui_get_object(self, "offline")); /* Load components */ site_setup(self); time_setup(self); - opengl_setup(self); return self; } -AWeatherView *aweather_gui_get_view(AWeatherGui *gui) +GisWorld *aweather_gui_get_world(AWeatherGui *self) { - g_assert(AWEATHER_IS_GUI(gui)); - return gui->view; + g_assert(AWEATHER_IS_GUI(self)); + return self->world; } -GtkBuilder *aweather_gui_get_builder(AWeatherGui *gui) +GisView *aweather_gui_get_view(AWeatherGui *self) +{ + g_assert(AWEATHER_IS_GUI(self)); + return self->view; +} +GisOpenGL *aweather_gui_get_opengl(AWeatherGui *self) +{ + g_assert(AWEATHER_IS_GUI(self)); + return self->opengl; +} +GtkBuilder *aweather_gui_get_builder(AWeatherGui *self) { g_debug("AWeatherGui: get_builder"); - g_assert(AWEATHER_IS_GUI(gui)); - return gui->builder; + g_assert(AWEATHER_IS_GUI(self)); + return self->builder; } -GtkWidget *aweather_gui_get_widget(AWeatherGui *gui, const gchar *name) +GtkWidget *aweather_gui_get_widget(AWeatherGui *self, const gchar *name) { g_debug("AWeatherGui: get_widget - name=%s", name); - g_assert(AWEATHER_IS_GUI(gui)); - GObject *widget = gtk_builder_get_object(gui->builder, name); + g_assert(AWEATHER_IS_GUI(self)); + GObject *widget = gtk_builder_get_object(self->builder, name); if (!GTK_IS_WIDGET(widget)) g_error("Failed to get widget `%s'", name); return GTK_WIDGET(widget); } -GObject *aweather_gui_get_object(AWeatherGui *gui, const gchar *name) +GObject *aweather_gui_get_object(AWeatherGui *self, const gchar *name) { g_debug("AWeatherGui: get_widget - name=%s", name); - g_assert(AWEATHER_IS_GUI(gui)); - return gtk_builder_get_object(gui->builder, name); + g_assert(AWEATHER_IS_GUI(self)); + return gtk_builder_get_object(self->builder, name); } -void aweather_gui_register_plugin(AWeatherGui *gui, AWeatherPlugin *plugin) +void aweather_gui_register_plugin(AWeatherGui *self, AWeatherPlugin *plugin) { g_debug("AWeatherGui: register_plugin"); - gui->plugins = g_list_append(gui->plugins, plugin); -} -void aweather_gui_gl_redraw(AWeatherGui *gui) -{ - g_debug("AWeatherGui: gl_redraw"); - GtkWidget *drawing = aweather_gui_get_widget(gui, "drawing"); - gtk_widget_queue_draw(drawing); -} -void aweather_gui_gl_begin(AWeatherGui *gui) -{ - g_assert(AWEATHER_IS_GUI(gui)); - - GtkDrawingArea *drawing = GTK_DRAWING_AREA(aweather_gui_get_widget(gui, "drawing")); - GdkGLContext *glcontext = gtk_widget_get_gl_context(GTK_WIDGET(drawing)); - GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(drawing)); - - if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) - g_assert_not_reached(); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -} -void aweather_gui_gl_end(AWeatherGui *gui) -{ - g_assert(AWEATHER_IS_GUI(gui)); - GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current(); - gdk_gl_drawable_gl_end(gldrawable); -} -void aweather_gui_gl_flush(AWeatherGui *gui) -{ - g_assert(AWEATHER_IS_GUI(gui)); - GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current(); - if (gdk_gl_drawable_is_double_buffered(gldrawable)) - gdk_gl_drawable_swap_buffers(gldrawable); - else - glFlush(); - gdk_gl_drawable_gl_end(gldrawable); + self->plugins = g_list_append(self->plugins, plugin); } diff --git a/src/aweather-gui.h b/src/aweather-gui.h index 27383b2..020aed6 100644 --- a/src/aweather-gui.h +++ b/src/aweather-gui.h @@ -20,7 +20,9 @@ #include #include -#include "aweather-view.h" +#include "gis-opengl.h" +#include "gis-world.h" +#include "gis-view.h" #include "aweather-plugin.h" /* Type macros */ @@ -38,9 +40,11 @@ struct _AWeatherGui { GtkWindow parent_instance; /* instance members */ - AWeatherView *view; - GtkBuilder *builder; - GList *plugins; + GisWorld *world; + GisView *view; + GisOpenGL *opengl; + GtkBuilder *builder; + GList *plugins; }; struct _AWeatherGuiClass { @@ -53,13 +57,14 @@ GType aweather_gui_get_type(void); /* Methods */ AWeatherGui *aweather_gui_new(); -AWeatherView *aweather_gui_get_view(AWeatherGui *gui); + +GisWorld *aweather_gui_get_world(AWeatherGui *gui); +GisOpenGL *aweather_gui_get_opengl(AWeatherGui *gui); +GisView *aweather_gui_get_view(AWeatherGui *gui); + GtkWidget *aweather_gui_get_widget(AWeatherGui *gui, const gchar *name); GObject *aweather_gui_get_object(AWeatherGui *gui, const gchar *name); + void aweather_gui_register_plugin(AWeatherGui *gui, AWeatherPlugin *plugin); -void aweather_gui_gl_redraw(AWeatherGui *gui); -void aweather_gui_gl_begin(AWeatherGui *gui); -void aweather_gui_gl_end(AWeatherGui *gui); -void aweather_gui_gl_flush(AWeatherGui *gui); #endif diff --git a/src/aweather-view.c b/src/aweather-view.c deleted file mode 100644 index 0c765fb..0000000 --- a/src/aweather-view.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright (C) 2009 Andy Spencer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "marshal.h" -#include "aweather-view.h" - -/**************** - * GObject code * - ****************/ -/* Constants */ -enum { - PROP_0, - PROP_TIME, - PROP_SITE, -}; -enum { - SIG_TIME_CHANGED, - SIG_SITE_CHANGED, - SIG_LOCATION_CHANGED, - SIG_ROTATION_CHANGED, - SIG_REFRESH, - SIG_OFFLINE, - NUM_SIGNALS, -}; -static guint signals[NUM_SIGNALS]; - -/* Class/Object init */ -G_DEFINE_TYPE(AWeatherView, aweather_view, G_TYPE_OBJECT); -static void aweather_view_init(AWeatherView *self) -{ - g_debug("AWeatherView: init"); - /* Default values */ - self->time = g_strdup(""); - self->site = g_strdup(""); - self->location[0] = 0; - self->location[1] = 0; - self->location[2] = -300*1000; - self->rotation[0] = 0; - self->rotation[1] = 0; - self->rotation[2] = 0; - self->offline = FALSE; -} -static void aweather_view_dispose(GObject *gobject) -{ - g_debug("AWeatherView: dispose"); - /* Drop references to other GObjects */ - G_OBJECT_CLASS(aweather_view_parent_class)->dispose(gobject); -} -static void aweather_view_finalize(GObject *gobject) -{ - g_debug("AWeatherView: finalize"); - AWeatherView *self = AWEATHER_VIEW(gobject); - g_free(self->time); - g_free(self->site); - G_OBJECT_CLASS(aweather_view_parent_class)->finalize(gobject); -} -static void aweather_view_set_property(GObject *object, guint property_id, - const GValue *value, GParamSpec *pspec) -{ - g_debug("AWeatherView: set_property"); - AWeatherView *self = AWEATHER_VIEW(object); - switch (property_id) { - case PROP_TIME: aweather_view_set_time(self, g_value_get_string(value)); break; - case PROP_SITE: aweather_view_set_site(self, g_value_get_string(value)); break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - } -} -static void aweather_view_get_property(GObject *object, guint property_id, - GValue *value, GParamSpec *pspec) -{ - g_debug("AWeatherView: get_property"); - AWeatherView *self = AWEATHER_VIEW(object); - switch (property_id) { - case PROP_TIME: g_value_set_string(value, aweather_view_get_time(self)); break; - case PROP_SITE: g_value_set_string(value, aweather_view_get_site(self)); break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - } -} -static void aweather_view_class_init(AWeatherViewClass *klass) -{ - g_debug("AWeatherView: class_init"); - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->dispose = aweather_view_dispose; - gobject_class->finalize = aweather_view_finalize; - gobject_class->get_property = aweather_view_get_property; - gobject_class->set_property = aweather_view_set_property; - g_object_class_install_property(gobject_class, PROP_TIME, - g_param_spec_pointer( - "time", - "time of the current frame", - "(format unknown)", - G_PARAM_READWRITE)); - g_object_class_install_property(gobject_class, PROP_SITE, - g_param_spec_pointer( - "site", - "site seen by the viewport", - "Site of the viewport. Currently this is the name of the radar site.", - G_PARAM_READWRITE)); - signals[SIG_TIME_CHANGED] = g_signal_new( - "time-changed", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, - 1, - G_TYPE_STRING); - signals[SIG_SITE_CHANGED] = g_signal_new( - "site-changed", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, - 1, - G_TYPE_STRING); - signals[SIG_LOCATION_CHANGED] = g_signal_new( - "location-changed", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - aweather_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE, - G_TYPE_NONE, - 3, - G_TYPE_DOUBLE, - G_TYPE_DOUBLE, - G_TYPE_DOUBLE); - signals[SIG_ROTATION_CHANGED] = g_signal_new( - "rotation-changed", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - aweather_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE, - G_TYPE_NONE, - 3, - G_TYPE_DOUBLE, - G_TYPE_DOUBLE, - G_TYPE_DOUBLE); - signals[SIG_REFRESH] = g_signal_new( - "refresh", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); - signals[SIG_OFFLINE] = g_signal_new( - "offline", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, - 1, - G_TYPE_BOOLEAN); -} - -/* Signal helpers */ -static void _aweather_view_emit_location_changed(AWeatherView *view) -{ - g_signal_emit(view, signals[SIG_LOCATION_CHANGED], 0, - view->location[0], - view->location[1], - view->location[2]); -} -static void _aweather_view_emit_rotation_changed(AWeatherView *view) -{ - g_signal_emit(view, signals[SIG_ROTATION_CHANGED], 0, - view->rotation[0], - view->rotation[1], - view->rotation[2]); -} -static void _aweather_view_emit_time_changed(AWeatherView *view) -{ - g_signal_emit(view, signals[SIG_TIME_CHANGED], 0, - view->time); -} -static void _aweather_view_emit_site_changed(AWeatherView *view) -{ - g_signal_emit(view, signals[SIG_SITE_CHANGED], 0, - view->site); -} -static void _aweather_view_emit_refresh(AWeatherView *view) -{ - g_signal_emit(view, signals[SIG_REFRESH], 0); -} -static void _aweather_view_emit_offline(AWeatherView *view) -{ - g_signal_emit(view, signals[SIG_OFFLINE], 0, - view->offline); -} - - -/*********** - * Methods * - ***********/ -AWeatherView *aweather_view_new() -{ - g_debug("AWeatherView: new"); - return g_object_new(AWEATHER_TYPE_VIEW, NULL); -} - -void aweather_view_set_time(AWeatherView *view, const char *time) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: set_time - time=%s", time); - g_free(view->time); - view->time = g_strdup(time); - _aweather_view_emit_time_changed(view); -} - -gchar *aweather_view_get_time(AWeatherView *view) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: get_time"); - return view->time; -} - -void aweather_view_set_location(AWeatherView *view, gdouble x, gdouble y, gdouble z) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: set_location"); - view->location[0] = x; - view->location[1] = y; - view->location[2] = z; - _aweather_view_emit_location_changed(view); -} - -void aweather_view_get_location(AWeatherView *view, gdouble *x, gdouble *y, gdouble *z) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: get_location"); - *x = view->location[0]; - *y = view->location[1]; - *z = view->location[2]; -} - -void aweather_view_pan(AWeatherView *view, gdouble x, gdouble y, gdouble z) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: pan - x=%.0f, y=%.0f, z=%.0f", x, y, z); - view->location[0] += x; - view->location[1] += y; - view->location[2] += z; - _aweather_view_emit_location_changed(view); -} - -void aweather_view_zoom(AWeatherView *view, gdouble scale) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: zoom"); - view->location[2] *= scale; - _aweather_view_emit_location_changed(view); -} - -void aweather_view_set_rotation(AWeatherView *view, gdouble x, gdouble y, gdouble z) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: set_rotation"); - view->rotation[0] = x; - view->rotation[1] = y; - view->rotation[2] = z; - _aweather_view_emit_rotation_changed(view); -} - -void aweather_view_get_rotation(AWeatherView *view, gdouble *x, gdouble *y, gdouble *z) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: get_rotation"); - *x = view->rotation[0]; - *y = view->rotation[1]; - *z = view->rotation[2]; -} - -void aweather_view_rotate(AWeatherView *view, gdouble x, gdouble y, gdouble z) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: rotate - x=%.0f, y=%.0f, z=%.0f", x, y, z); - view->rotation[0] += x; - view->rotation[1] += y; - view->rotation[2] += z; - _aweather_view_emit_rotation_changed(view); -} - -void aweather_view_refresh(AWeatherView *view) -{ - g_debug("AWeatherView: refresh"); - _aweather_view_emit_refresh(view); -} - -void aweather_view_set_offline(AWeatherView *view, gboolean offline) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: set_offline - %d", offline); - view->offline = offline; - _aweather_view_emit_offline(view); -} - -gboolean aweather_view_get_offline(AWeatherView *view) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: get_offline - %d", view->offline); - return view->offline; -} - -/* To be deprecated, use {get,set}_location */ -void aweather_view_set_site(AWeatherView *view, const gchar *site) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: set_site"); - g_free(view->site); - view->site = g_strdup(site); - _aweather_view_emit_site_changed(view); -} - -gchar *aweather_view_get_site(AWeatherView *view) -{ - g_assert(AWEATHER_IS_VIEW(view)); - g_debug("AWeatherView: get_site"); - return view->site; -} diff --git a/src/aweather-view.h b/src/aweather-view.h deleted file mode 100644 index c67c8d8..0000000 --- a/src/aweather-view.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2009 Andy Spencer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __AWEATHER_VIEW_H__ -#define __AWEATHER_VIEW_H__ - -#include - -/* Type macros */ -#define AWEATHER_TYPE_VIEW (aweather_view_get_type()) -#define AWEATHER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), AWEATHER_TYPE_VIEW, AWeatherView)) -#define AWEATHER_IS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), AWEATHER_TYPE_VIEW)) -#define AWEATHER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), AWEATHER_TYPE_VIEW, AWeatherViewClass)) -#define AWEATHER_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), AWEATHER_TYPE_VIEW)) -#define AWEATHER_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), AWEATHER_TYPE_VIEW, AWeatherViewClass)) - -typedef struct _AWeatherView AWeatherView; -typedef struct _AWeatherViewClass AWeatherViewClass; - -struct _AWeatherView { - GObject parent_instance; - - /* instance members */ - gchar *time; - gchar *site; - gdouble location[3]; - gdouble rotation[3]; - gboolean offline; -}; - -struct _AWeatherViewClass { - GObjectClass parent_class; - - /* class members */ -}; - -GType aweather_view_get_type(void); - -/* Methods */ -AWeatherView *aweather_view_new(); - -void aweather_view_set_time(AWeatherView *view, const gchar *time); -gchar *aweather_view_get_time(AWeatherView *view); - -void aweather_view_set_location(AWeatherView *view, gdouble x, gdouble y, gdouble z); -void aweather_view_get_location(AWeatherView *view, gdouble *x, gdouble *y, gdouble *z); -void aweather_view_pan (AWeatherView *view, gdouble x, gdouble y, gdouble z); -void aweather_view_zoom (AWeatherView *view, gdouble scale); - -void aweather_view_set_rotation(AWeatherView *view, gdouble x, gdouble y, gdouble z); -void aweather_view_get_rotation(AWeatherView *view, gdouble *x, gdouble *y, gdouble *z); -void aweather_view_rotate (AWeatherView *view, gdouble x, gdouble y, gdouble z); - -void aweather_view_refresh(AWeatherView *view); - -void aweather_view_set_offline(AWeatherView *view, gboolean offline); -gboolean aweather_view_get_offline(AWeatherView *view); - -/* To be deprecated, use {get,set}_location */ -void aweather_view_set_site(AWeatherView *view, const gchar *site); -gchar *aweather_view_get_site(AWeatherView *view); - -#endif diff --git a/src/gis-opengl.c b/src/gis-opengl.c new file mode 100644 index 0000000..46eae60 --- /dev/null +++ b/src/gis-opengl.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2009 Andy Spencer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "misc.h" +#include "aweather-gui.h" +#include "gis-world.h" +#include "gis-view.h" +#include "gis-opengl.h" + +/**************** + * GObject code * + ****************/ +G_DEFINE_TYPE(GisOpenGL, gis_opengl, G_TYPE_OBJECT); +static void gis_opengl_init(GisOpenGL *self) +{ + g_debug("GisOpenGL: init"); +} +static GObject *gis_opengl_constructor(GType gtype, guint n_properties, + GObjectConstructParam *properties) +{ + g_debug("gis_opengl: constructor"); + GObjectClass *parent_class = G_OBJECT_CLASS(gis_opengl_parent_class); + return parent_class->constructor(gtype, n_properties, properties); +} +static void gis_opengl_dispose(GObject *gobject) +{ + g_debug("GisOpenGL: dispose"); + GisOpenGL *self = GIS_OPENGL(gobject); + if (self->world) { + g_object_unref(self->world); + self->world = NULL; + } + if (self->view) { + g_object_unref(self->view); + self->view = NULL; + } + if (self->drawing) { + g_object_unref(self->drawing); + self->drawing = NULL; + } + G_OBJECT_CLASS(gis_opengl_parent_class)->dispose(gobject); +} +static void gis_opengl_finalize(GObject *gobject) +{ + g_debug("GisOpenGL: finalize"); + G_OBJECT_CLASS(gis_opengl_parent_class)->finalize(gobject); + gtk_main_quit(); + +} +static void gis_opengl_class_init(GisOpenGLClass *klass) +{ + g_debug("GisOpenGL: class_init"); + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->constructor = gis_opengl_constructor; + gobject_class->dispose = gis_opengl_dispose; + gobject_class->finalize = gis_opengl_finalize; +} + +/************* + * Callbacks * + *************/ +gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, GisOpenGL *self) +{ + g_debug("GisOpenGL: on_drawing_button_press - Grabbing focus"); + gtk_widget_grab_focus(GTK_WIDGET(self->drawing)); + return TRUE; +} +gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, GisOpenGL *self) +{ + g_debug("GisOpenGL: on_drawing_key_press - key=%x, state=%x, plus=%x", + event->keyval, event->state, GDK_plus); + double x,y,z; + gis_view_get_location(self->view, &x, &y, &z); + guint kv = event->keyval; + if (kv == GDK_Left || kv == GDK_h) gis_view_pan(self->view, -z/10, 0, 0); + else if (kv == GDK_Down || kv == GDK_j) gis_view_pan(self->view, 0, -z/10, 0); + else if (kv == GDK_Up || kv == GDK_k) gis_view_pan(self->view, 0, z/10, 0); + else if (kv == GDK_Right || kv == GDK_l) gis_view_pan(self->view, z/10, 0, 0); + else if (kv == GDK_minus || kv == GDK_o) gis_view_zoom(self->view, 10./9); + else if (kv == GDK_plus || kv == GDK_i) gis_view_zoom(self->view, 9./10); + else if (kv == GDK_H ) gis_view_rotate(self->view, 0, -10, 0); + else if (kv == GDK_J ) gis_view_rotate(self->view, 10, 0, 0); + else if (kv == GDK_K ) gis_view_rotate(self->view, -10, 0, 0); + else if (kv == GDK_L ) gis_view_rotate(self->view, 0, 10, 0); + return TRUE; +} + + +gboolean on_map(GtkWidget *drawing, GdkEventConfigure *event, GisOpenGL *self) +{ + g_debug("GisOpenGL: on_map"); + + /* Misc */ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + /* Tessellation, "finding intersecting triangles" */ + /* http://research.microsoft.com/pubs/70307/tr-2006-81.pdf */ + /* http://www.opengl.org/wiki/Alpha_Blending */ + glAlphaFunc(GL_GREATER,0.1); + glEnable(GL_ALPHA_TEST); + + /* Depth test */ + glClearDepth(1.0); + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + + gis_opengl_end(self); + return FALSE; +} + +gboolean on_configure(GtkWidget *drawing, GdkEventConfigure *event, GisOpenGL *self) +{ + g_debug("GisOpenGL: on_confiure"); + gis_opengl_begin(self); + + double x, y, z; + gis_view_get_location(self->view, &x, &y, &z); + + /* Window is at 500 m from camera */ + double width = GTK_WIDGET(self->drawing)->allocation.width; + double height = GTK_WIDGET(self->drawing)->allocation.height; + + glViewport(0, 0, width, height); + + /* Perspective */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + double ang = atan((height/2)/500); + + //gluPerspective(r2d(ang)*2, width/height, -z-20, -z+20); + gluPerspective(r2d(ang)*2, width/height, 1, 500*1000); + + gis_opengl_end(self); + return FALSE; +} + +gboolean on_expose(GtkWidget *drawing, GdkEventExpose *event, GisOpenGL *self) +{ + g_debug("GisOpenGL: on_expose - begin"); + gis_opengl_begin(self); + + double lx, ly, lz; + double rx, ry, rz; + gis_view_get_location(self->view, &lx, &ly, &lz); + gis_view_get_rotation(self->view, &rx, &ry, &rz); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(lx, ly, lz); + glRotatef(rx, 1, 0, 0); + glRotatef(ry, 0, 1, 0); + glRotatef(rz, 0, 0, 1); + + /* Expose plugins */ + /* TODO: Figure out how to handle plugins: + * - Do they belong to AWeatherGui, GisOpenGL, etc? + */ + for (GList *cur = self->plugins; cur; cur = cur->next) { + AWeatherPlugin *plugin = AWEATHER_PLUGIN(cur->data); + aweather_plugin_expose(plugin); + } + + gis_opengl_end(self); + gis_opengl_flush(self); + g_debug("GisOpenGL: on_expose - end\n"); + return FALSE; +} + +void on_state_changed(GisView *view, + gdouble x, gdouble y, gdouble z, GisOpenGL *self) +{ + /* Reset clipping area and redraw */ + on_configure(NULL, NULL, self); + gis_opengl_redraw(self); +} + +/*********** + * Methods * + ***********/ +GisOpenGL *gis_opengl_new(GisWorld *world, GisView *view, GtkDrawingArea *drawing) +{ + g_debug("GisOpenGL: new"); + GisOpenGL *self = g_object_new(GIS_TYPE_OPENGL, NULL); + self->world = world; + self->view = view; + self->drawing = drawing; + g_object_ref(world); + g_object_ref(view); + g_object_ref(drawing); + + /* OpenGL setup */ + GdkGLConfig *glconfig = gdk_gl_config_new_by_mode( + GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH | + GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA); + if (!glconfig) + g_error("Failed to create glconfig"); + if (!gtk_widget_set_gl_capability(GTK_WIDGET(self->drawing), + glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE)) + g_error("GL lacks required capabilities"); + + g_signal_connect(self->view, "location-changed", G_CALLBACK(on_state_changed), self); + g_signal_connect(self->view, "rotation-changed", G_CALLBACK(on_state_changed), self); + + g_signal_connect(self->drawing, "map-event", G_CALLBACK(on_map), self); + g_signal_connect(self->drawing, "configure-event", G_CALLBACK(on_configure), self); + g_signal_connect(self->drawing, "expose-event", G_CALLBACK(on_expose), self); + + g_signal_connect(self->drawing, "button-press-event", G_CALLBACK(on_button_press), self); + g_signal_connect(self->drawing, "enter-notify-event", G_CALLBACK(on_button_press), self); + g_signal_connect(self->drawing, "key-press-event", G_CALLBACK(on_key_press), self); + return self; +} + +void gis_opengl_redraw(GisOpenGL *self) +{ + g_debug("GisOpenGL: gl_redraw"); + gtk_widget_queue_draw(GTK_WIDGET(self->drawing)); +} +void gis_opengl_begin(GisOpenGL *self) +{ + g_assert(GIS_IS_OPENGL(self)); + + GdkGLContext *glcontext = gtk_widget_get_gl_context(GTK_WIDGET(self->drawing)); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(self->drawing)); + + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) + g_assert_not_reached(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} +void gis_opengl_end(GisOpenGL *self) +{ + g_assert(GIS_IS_OPENGL(self)); + GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current(); + gdk_gl_drawable_gl_end(gldrawable); +} +void gis_opengl_flush(GisOpenGL *self) +{ + g_assert(GIS_IS_OPENGL(self)); + GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current(); + if (gdk_gl_drawable_is_double_buffered(gldrawable)) + gdk_gl_drawable_swap_buffers(gldrawable); + else + glFlush(); + gdk_gl_drawable_gl_end(gldrawable); +} diff --git a/src/gis-opengl.h b/src/gis-opengl.h new file mode 100644 index 0000000..aca186f --- /dev/null +++ b/src/gis-opengl.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2009 Andy Spencer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIS_OPENGL_H__ +#define __GIS_OPENGL_H__ + +#include +#include +#include +#include + +#include "gis-view.h" +#include "gis-world.h" + +/* Type macros */ +#define GIS_TYPE_OPENGL (gis_opengl_get_type()) +#define GIS_OPENGL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GIS_TYPE_OPENGL, GisOpenGL)) +#define GIS_IS_OPENGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIS_TYPE_OPENGL)) +#define GIS_OPENGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_OPENGL, GisOpenGLClass)) +#define GIS_IS_OPENGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_OPENGL)) +#define GIS_OPENGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_OPENGL, GisOpenGLClass)) + +typedef struct _GisOpenGL GisOpenGL; +typedef struct _GisOpenGLClass GisOpenGLClass; + +struct _GisOpenGL { + GObject parent_instance; + + /* instance members */ + GisWorld *world; + GisView *view; + GtkDrawingArea *drawing; + GList *plugins; +}; + +struct _GisOpenGLClass { + GObjectClass parent_class; + + /* class members */ +}; + +GType gis_opengl_get_type(void); + +/* Methods */ +GisOpenGL *gis_opengl_new(GisWorld *world, GisView *view, GtkDrawingArea *drawing); + +void gis_opengl_redraw(GisOpenGL *gis); +void gis_opengl_begin(GisOpenGL *gis); +void gis_opengl_end(GisOpenGL *gis); +void gis_opengl_flush(GisOpenGL *gis); + +#endif diff --git a/src/gis-view.c b/src/gis-view.c new file mode 100644 index 0000000..e43aefb --- /dev/null +++ b/src/gis-view.c @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2009 Andy Spencer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "marshal.h" +#include "gis-view.h" + +/**************** + * GObject code * + ****************/ +/* Constants */ +enum { + PROP_0, + PROP_TIME, + PROP_SITE, +}; +enum { + SIG_TIME_CHANGED, + SIG_SITE_CHANGED, + SIG_LOCATION_CHANGED, + SIG_ROTATION_CHANGED, + NUM_SIGNALS, +}; +static guint signals[NUM_SIGNALS]; + +/* Class/Object init */ +G_DEFINE_TYPE(GisView, gis_view, G_TYPE_OBJECT); +static void gis_view_init(GisView *self) +{ + g_debug("GisView: init"); + /* Default values */ + self->time = g_strdup(""); + self->site = g_strdup(""); + self->location[0] = 0; + self->location[1] = 0; + self->location[2] = -300*1000; + self->rotation[0] = 0; + self->rotation[1] = 0; + self->rotation[2] = 0; +} +static void gis_view_dispose(GObject *gobject) +{ + g_debug("GisView: dispose"); + /* Drop references to other GObjects */ + G_OBJECT_CLASS(gis_view_parent_class)->dispose(gobject); +} +static void gis_view_finalize(GObject *gobject) +{ + g_debug("GisView: finalize"); + GisView *self = GIS_VIEW(gobject); + g_free(self->time); + g_free(self->site); + G_OBJECT_CLASS(gis_view_parent_class)->finalize(gobject); +} +static void gis_view_set_property(GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + g_debug("GisView: set_property"); + GisView *self = GIS_VIEW(object); + switch (property_id) { + case PROP_TIME: gis_view_set_time(self, g_value_get_string(value)); break; + case PROP_SITE: gis_view_set_site(self, g_value_get_string(value)); break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } +} +static void gis_view_get_property(GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + g_debug("GisView: get_property"); + GisView *self = GIS_VIEW(object); + switch (property_id) { + case PROP_TIME: g_value_set_string(value, gis_view_get_time(self)); break; + case PROP_SITE: g_value_set_string(value, gis_view_get_site(self)); break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } +} +static void gis_view_class_init(GisViewClass *klass) +{ + g_debug("GisView: class_init"); + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->dispose = gis_view_dispose; + gobject_class->finalize = gis_view_finalize; + gobject_class->get_property = gis_view_get_property; + gobject_class->set_property = gis_view_set_property; + g_object_class_install_property(gobject_class, PROP_TIME, + g_param_spec_pointer( + "time", + "time of the current frame", + "(format unknown)", + G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, PROP_SITE, + g_param_spec_pointer( + "site", + "site seen by the viewport", + "Site of the viewport. Currently this is the name of the radar site.", + G_PARAM_READWRITE)); + signals[SIG_TIME_CHANGED] = g_signal_new( + "time-changed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + signals[SIG_SITE_CHANGED] = g_signal_new( + "site-changed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + signals[SIG_LOCATION_CHANGED] = g_signal_new( + "location-changed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + aweather_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE, + G_TYPE_NONE, + 3, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE); + signals[SIG_ROTATION_CHANGED] = g_signal_new( + "rotation-changed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + aweather_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE, + G_TYPE_NONE, + 3, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE); +} + +/* Signal helpers */ +static void _gis_view_emit_location_changed(GisView *view) +{ + g_signal_emit(view, signals[SIG_LOCATION_CHANGED], 0, + view->location[0], + view->location[1], + view->location[2]); +} +static void _gis_view_emit_rotation_changed(GisView *view) +{ + g_signal_emit(view, signals[SIG_ROTATION_CHANGED], 0, + view->rotation[0], + view->rotation[1], + view->rotation[2]); +} +static void _gis_view_emit_time_changed(GisView *view) +{ + g_signal_emit(view, signals[SIG_TIME_CHANGED], 0, + view->time); +} +static void _gis_view_emit_site_changed(GisView *view) +{ + g_signal_emit(view, signals[SIG_SITE_CHANGED], 0, + view->site); +} + + +/*********** + * Methods * + ***********/ +GisView *gis_view_new() +{ + g_debug("GisView: new"); + return g_object_new(GIS_TYPE_VIEW, NULL); +} + +void gis_view_set_time(GisView *view, const char *time) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: set_time - time=%s", time); + g_free(view->time); + view->time = g_strdup(time); + _gis_view_emit_time_changed(view); +} + +gchar *gis_view_get_time(GisView *view) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: get_time"); + return view->time; +} + +void gis_view_set_location(GisView *view, gdouble x, gdouble y, gdouble z) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: set_location"); + view->location[0] = x; + view->location[1] = y; + view->location[2] = z; + _gis_view_emit_location_changed(view); +} + +void gis_view_get_location(GisView *view, gdouble *x, gdouble *y, gdouble *z) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: get_location"); + *x = view->location[0]; + *y = view->location[1]; + *z = view->location[2]; +} + +void gis_view_pan(GisView *view, gdouble x, gdouble y, gdouble z) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: pan - x=%.0f, y=%.0f, z=%.0f", x, y, z); + view->location[0] += x; + view->location[1] += y; + view->location[2] += z; + _gis_view_emit_location_changed(view); +} + +void gis_view_zoom(GisView *view, gdouble scale) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: zoom"); + view->location[2] *= scale; + _gis_view_emit_location_changed(view); +} + +void gis_view_set_rotation(GisView *view, gdouble x, gdouble y, gdouble z) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: set_rotation"); + view->rotation[0] = x; + view->rotation[1] = y; + view->rotation[2] = z; + _gis_view_emit_rotation_changed(view); +} + +void gis_view_get_rotation(GisView *view, gdouble *x, gdouble *y, gdouble *z) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: get_rotation"); + *x = view->rotation[0]; + *y = view->rotation[1]; + *z = view->rotation[2]; +} + +void gis_view_rotate(GisView *view, gdouble x, gdouble y, gdouble z) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: rotate - x=%.0f, y=%.0f, z=%.0f", x, y, z); + view->rotation[0] += x; + view->rotation[1] += y; + view->rotation[2] += z; + _gis_view_emit_rotation_changed(view); +} + +/* To be deprecated, use {get,set}_location */ +void gis_view_set_site(GisView *view, const gchar *site) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: set_site"); + g_free(view->site); + view->site = g_strdup(site); + _gis_view_emit_site_changed(view); +} + +gchar *gis_view_get_site(GisView *view) +{ + g_assert(GIS_IS_VIEW(view)); + g_debug("GisView: get_site"); + return view->site; +} diff --git a/src/gis-view.h b/src/gis-view.h new file mode 100644 index 0000000..4608788 --- /dev/null +++ b/src/gis-view.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2009 Andy Spencer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIS_VIEW_H__ +#define __GIS_VIEW_H__ + +#include + +/* Type macros */ +#define GIS_TYPE_VIEW (gis_view_get_type()) +#define GIS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GIS_TYPE_VIEW, GisView)) +#define GIS_IS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIS_TYPE_VIEW)) +#define GIS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_VIEW, GisViewClass)) +#define GIS_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_VIEW)) +#define GIS_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_VIEW, GisViewClass)) + +typedef struct _GisView GisView; +typedef struct _GisViewClass GisViewClass; + +struct _GisView { + GObject parent_instance; + + /* instance members */ + gchar *time; + gchar *site; + gdouble location[3]; + gdouble rotation[3]; +}; + +struct _GisViewClass { + GObjectClass parent_class; + + /* class members */ +}; + +GType gis_view_get_type(void); + +/* Methods */ +GisView *gis_view_new(); + +void gis_view_set_time(GisView *view, const gchar *time); +gchar *gis_view_get_time(GisView *view); + +void gis_view_set_location(GisView *view, gdouble x, gdouble y, gdouble z); +void gis_view_get_location(GisView *view, gdouble *x, gdouble *y, gdouble *z); +void gis_view_pan (GisView *view, gdouble x, gdouble y, gdouble z); +void gis_view_zoom (GisView *view, gdouble scale); + +void gis_view_set_rotation(GisView *view, gdouble x, gdouble y, gdouble z); +void gis_view_get_rotation(GisView *view, gdouble *x, gdouble *y, gdouble *z); +void gis_view_rotate (GisView *view, gdouble x, gdouble y, gdouble z); + +/* To be deprecated, use {get,set}_location */ +void gis_view_set_site(GisView *view, const gchar *site); +gchar *gis_view_get_site(GisView *view); + +#endif diff --git a/src/gis-world.c b/src/gis-world.c new file mode 100644 index 0000000..4350f3a --- /dev/null +++ b/src/gis-world.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2009 Andy Spencer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "marshal.h" +#include "gis-world.h" + +/**************** + * GObject code * + ****************/ +/* Constants */ +enum { + SIG_REFRESH, + SIG_OFFLINE, + NUM_SIGNALS, +}; +static guint signals[NUM_SIGNALS]; + +/* Class/Object init */ +G_DEFINE_TYPE(GisWorld, gis_world, G_TYPE_OBJECT); +static void gis_world_init(GisWorld *self) +{ + g_debug("GisWorld: init"); + /* Default values */ + self->offline = FALSE; +} +static void gis_world_dispose(GObject *gobject) +{ + g_debug("GisWorld: dispose"); + /* Drop references to other GObjects */ + G_OBJECT_CLASS(gis_world_parent_class)->dispose(gobject); +} +static void gis_world_finalize(GObject *gobject) +{ + g_debug("GisWorld: finalize"); + GisWorld *self = GIS_WORLD(gobject); + G_OBJECT_CLASS(gis_world_parent_class)->finalize(gobject); +} +static void gis_world_class_init(GisWorldClass *klass) +{ + g_debug("GisWorld: class_init"); + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->dispose = gis_world_dispose; + gobject_class->finalize = gis_world_finalize; + signals[SIG_REFRESH] = g_signal_new( + "refresh", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals[SIG_OFFLINE] = g_signal_new( + "offline", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, + 1, + G_TYPE_BOOLEAN); +} + +/* Signal helpers */ +static void _gis_world_emit_refresh(GisWorld *world) +{ + g_signal_emit(world, signals[SIG_REFRESH], 0); +} +static void _gis_world_emit_offline(GisWorld *world) +{ + g_signal_emit(world, signals[SIG_OFFLINE], 0, + world->offline); +} + + +/*********** + * Methods * + ***********/ +GisWorld *gis_world_new() +{ + g_debug("GisWorld: new"); + return g_object_new(GIS_TYPE_WORLD, NULL); +} + +void gis_world_refresh(GisWorld *world) +{ + g_debug("GisWorld: refresh"); + _gis_world_emit_refresh(world); +} + +void gis_world_set_offline(GisWorld *world, gboolean offline) +{ + g_assert(GIS_IS_WORLD(world)); + g_debug("GisWorld: set_offline - %d", offline); + world->offline = offline; + _gis_world_emit_offline(world); +} + +gboolean gis_world_get_offline(GisWorld *world) +{ + g_assert(GIS_IS_WORLD(world)); + g_debug("GisWorld: get_offline - %d", world->offline); + return world->offline; +} diff --git a/src/gis-world.h b/src/gis-world.h new file mode 100644 index 0000000..64e52a2 --- /dev/null +++ b/src/gis-world.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009 Andy Spencer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIS_WORLD_H__ +#define __GIS_WORLD_H__ + +#include + +/* Type macros */ +#define GIS_TYPE_WORLD (gis_world_get_type()) +#define GIS_WORLD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GIS_TYPE_WORLD, GisWorld)) +#define GIS_IS_WORLD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIS_TYPE_WORLD)) +#define GIS_WORLD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_WORLD, GisWorldClass)) +#define GIS_IS_WORLD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_WORLD)) +#define GIS_WORLD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_WORLD, GisWorldClass)) + +typedef struct _GisWorld GisWorld; +typedef struct _GisWorldClass GisWorldClass; + +struct _GisWorld { + GObject parent_instance; + + /* instance members */ + gboolean offline; +}; + +struct _GisWorldClass { + GObjectClass parent_class; + + /* class members */ +}; + +GType gis_world_get_type(void); + +/* Methods */ +GisWorld *gis_world_new(); + +void gis_world_refresh(GisWorld *world); + +void gis_world_set_offline(GisWorld *world, gboolean offline); +gboolean gis_world_get_offline(GisWorld *world); + +#endif diff --git a/src/location.h b/src/location.h index 82cf38c..b030f04 100644 --- a/src/location.h +++ b/src/location.h @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -#ifndef __SITE_H__ -#define __SITE_H__ +#ifndef __LOCATION_H__ +#define __LOCATION_H__ enum { LOCATION_CITY, diff --git a/src/main.c b/src/main.c index 4923b37..843592c 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,8 @@ #include #include "aweather-gui.h" +#include "gis-view.h" +#include "gis-world.h" #include "plugin-radar.h" #include "plugin-ridge.h" #include "plugin-example.h" @@ -36,8 +38,8 @@ static void log_func(const gchar *log_domain, GLogLevelFlags log_level, static gulong on_map_id = 0; static gboolean on_map(AWeatherGui *gui, GdkEvent *event, gchar *site) { - AWeatherView *view = aweather_gui_get_view(gui); - aweather_view_set_site(view, site); + GisView *view = aweather_gui_get_view(gui); + gis_view_set_site(view, site); g_signal_handler_disconnect(gui, on_map_id); return FALSE; } @@ -78,15 +80,20 @@ int main(int argc, char *argv[]) g_log_set_handler(NULL, G_LOG_LEVEL_MASK, log_func, NULL); /* Set up AWeather */ + /* TODO: Figure out a better way to do plugins + * AWeatherPlugin interface for tabs? + * GisPlugin interface for expose? */ AWeatherGui *gui = aweather_gui_new(); - AWeatherView *view = aweather_gui_get_view(gui); - aweather_view_set_offline(view, opt_offline); + GisWorld *world = aweather_gui_get_world(gui); + GisOpenGL *opengl = aweather_gui_get_opengl(gui); + gis_world_set_offline(world, opt_offline); on_map_id = g_signal_connect(gui, "map-event", G_CALLBACK(on_map), opt_site); /* Load plugins */ aweather_gui_register_plugin(gui, AWEATHER_PLUGIN(aweather_example_new(gui))); aweather_gui_register_plugin(gui, AWEATHER_PLUGIN(aweather_ridge_new(gui))); aweather_gui_register_plugin(gui, AWEATHER_PLUGIN(aweather_radar_new(gui))); + opengl->plugins = gui->plugins; gtk_widget_show_all(GTK_WIDGET(gui)); gtk_main(); diff --git a/src/plugin-example.c b/src/plugin-example.c index f2ae95e..d81f11a 100644 --- a/src/plugin-example.c +++ b/src/plugin-example.c @@ -73,12 +73,12 @@ static void aweather_example_class_init(AWeatherExampleClass *klass) /*********** * Helpers * ***********/ -static gboolean rotate(gpointer _example) +static gboolean rotate(gpointer _self) { - AWeatherExample *example = _example; - if (gtk_toggle_button_get_active(example->button)) { - example->rotation += 1.0; - aweather_gui_gl_redraw(example->gui); + AWeatherExample *self = _self; + if (gtk_toggle_button_get_active(self->button)) { + self->rotation += 1.0; + gis_opengl_redraw(aweather_gui_get_opengl(self->gui)); } return TRUE; } diff --git a/src/plugin-radar.c b/src/plugin-radar.c index 23b6d3a..6ddc402 100644 --- a/src/plugin-radar.c +++ b/src/plugin-radar.c @@ -122,7 +122,8 @@ static void bscan_sweep(AWeatherRadar *self, Sweep *sweep, colormap_t *colormap, /* Load a sweep as the active texture */ static void load_sweep(AWeatherRadar *self, Sweep *sweep) { - aweather_gui_gl_begin(self->gui); + GisOpenGL *opengl = aweather_gui_get_opengl(self->gui); + gis_opengl_begin(opengl); self->cur_sweep = sweep; int height, width; guint8 *data; @@ -137,8 +138,8 @@ static void load_sweep(AWeatherRadar *self, Sweep *sweep) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); g_free(data); - aweather_gui_gl_redraw(self->gui); - aweather_gui_gl_end(self->gui); + gis_opengl_redraw(opengl); + gis_opengl_end(opengl); } static void load_colormap(AWeatherRadar *self, gchar *table) @@ -385,8 +386,8 @@ static void update_times_gtk(AWeatherRadar *self, GList *times) } } - AWeatherView *view = aweather_gui_get_view(self->gui); - aweather_view_set_time(view, last_time); + GisView *view = aweather_gui_get_view(self->gui); + gis_view_set_time(view, last_time); g_regex_unref(regex); g_list_foreach(times, (GFunc)g_free, NULL); @@ -409,9 +410,10 @@ static void update_times_online_cb(char *path, gboolean updated, gpointer _self) update_times_gtk(_self, times); } -static void update_times(AWeatherRadar *self, AWeatherView *view, char *site) +static void update_times(AWeatherRadar *self, GisView *view, char *site) { - if (aweather_view_get_offline(view)) { + GisWorld *world = aweather_gui_get_world(self->gui); + if (gis_world_get_offline(world)) { GList *times = NULL; gchar *path = g_build_filename(g_get_user_cache_dir(), PACKAGE, "nexrd2", "raw", site, NULL); GDir *dir = g_dir_open(path, 0, NULL); @@ -514,12 +516,12 @@ static void on_sweep_clicked(GtkRadioButton *button, gpointer _self) load_sweep (self, g_object_get_data(G_OBJECT(button), "sweep")); } -static void on_time_changed(AWeatherView *view, const char *time, gpointer _self) +static void on_time_changed(GisView *view, const char *time, gpointer _self) { AWeatherRadar *self = AWEATHER_RADAR(_self); g_debug("AWeatherRadar: on_time_changed - setting time=%s", time); // format: http://mesonet.agron.iastate.edu/data/nexrd2/raw/KABR/KABR_20090510_0323 - char *site = aweather_view_get_site(view); + char *site = gis_view_get_site(view); char *path = g_strdup_printf("nexrd2/raw/%s/%s_%s", site, site, time); /* Set up progress bar */ @@ -540,14 +542,14 @@ static void on_time_changed(AWeatherView *view, const char *time, gpointer _self RSL_free_radar(self->cur_radar); self->cur_radar = NULL; self->cur_sweep = NULL; - aweather_gui_gl_redraw(self->gui); + gis_opengl_redraw(aweather_gui_get_opengl(self->gui)); /* Start loading the new radar */ if (self->soup) { soup_session_abort(self->soup); self->soup = NULL; } - if (aweather_view_get_offline(view)) + if (gis_world_get_offline(aweather_gui_get_world(self->gui))) self->soup = cache_file(nexrad_base, path, AWEATHER_ONCE, cache_chunk_cb, cache_done_cb, self); else @@ -556,17 +558,18 @@ static void on_time_changed(AWeatherView *view, const char *time, gpointer _self g_free(path); } -static void on_site_changed(AWeatherView *view, char *site, gpointer _self) +static void on_site_changed(GisView *view, char *site, gpointer _self) { AWeatherRadar *self = AWEATHER_RADAR(_self); g_debug("AWeatherRadar: on_site_changed - Loading wsr88d list for %s", site); - update_times(self, view, site), &time; + update_times(self, view, site); } -static void on_refresh(AWeatherView *view, gpointer _self) +static void on_refresh(GisWorld *world, gpointer _self) { AWeatherRadar *self = AWEATHER_RADAR(_self); - char *site = aweather_view_get_site(view); + GisView *view = aweather_gui_get_view(AWEATHER_RADAR(_self)->gui); + char *site = gis_view_get_site(view); update_times(self, view, site); } @@ -577,10 +580,9 @@ AWeatherRadar *aweather_radar_new(AWeatherGui *gui) { g_debug("AWeatherRadar: new"); AWeatherRadar *self = g_object_new(AWEATHER_TYPE_RADAR, NULL); - self->gui = gui; + self->gui = gui; GtkWidget *config = aweather_gui_get_widget(gui, "tabs"); - AWeatherView *view = aweather_gui_get_view(gui); /* Add configuration tab */ self->config_body = gtk_alignment_new(0, 0, 1, 1); @@ -589,9 +591,11 @@ AWeatherRadar *aweather_radar_new(AWeatherGui *gui) gtk_notebook_prepend_page(GTK_NOTEBOOK(config), self->config_body, gtk_label_new("Radar")); /* Set up OpenGL Stuff */ - g_signal_connect(view, "site-changed", G_CALLBACK(on_site_changed), self); - g_signal_connect(view, "time-changed", G_CALLBACK(on_time_changed), self); - g_signal_connect(view, "refresh", G_CALLBACK(on_refresh), self); + GisView *view = aweather_gui_get_view(gui); + GisWorld *world = aweather_gui_get_world(gui); + g_signal_connect(view, "site-changed", G_CALLBACK(on_site_changed), self); + g_signal_connect(view, "time-changed", G_CALLBACK(on_time_changed), self); + g_signal_connect(world, "refresh", G_CALLBACK(on_refresh), self); return self; } diff --git a/src/plugin-ridge.c b/src/plugin-ridge.c index 75927d9..c500dad 100644 --- a/src/plugin-ridge.c +++ b/src/plugin-ridge.c @@ -110,7 +110,8 @@ static layer_t layers[] = { */ void load_texture(AWeatherRidge *self, layer_t *layer, gchar *filename) { - aweather_gui_gl_begin(self->gui); + GisOpenGL *opengl = aweather_gui_get_opengl(self->gui); + gis_opengl_begin(opengl); /* Load image */ GError *error = NULL; @@ -142,12 +143,12 @@ void load_texture(AWeatherRidge *self, layer_t *layer, gchar *filename) base); g_free(base); - aweather_gui_gl_end(self->gui); + gis_opengl_end(opengl); g_object_unref(pixbuf); /* Redraw */ - aweather_gui_gl_redraw(self->gui); + gis_opengl_redraw(opengl); } @@ -168,7 +169,7 @@ void cached_cb(gchar *filename, gboolean updated, gpointer _udata) /************* * callbacks * *************/ -static void on_site_changed(AWeatherView *view, gchar *site, AWeatherRidge *self) +static void on_site_changed(GisView *view, gchar *site, AWeatherRidge *self) { g_debug("AWeatherRidge: on_site_changed - site=%s", site); for (int i = 0; i < LAYER_COUNT; i++) { @@ -183,11 +184,11 @@ static void on_site_changed(AWeatherView *view, gchar *site, AWeatherRidge *self } } -void toggle_layer(GtkToggleButton *check, AWeatherGui *gui) +void toggle_layer(GtkToggleButton *check, AWeatherRidge *self) { layer_t *layer = g_object_get_data(G_OBJECT(check), "layer"); layer->enabled = gtk_toggle_button_get_active(check); - aweather_gui_gl_redraw(gui); + gis_opengl_redraw(aweather_gui_get_opengl(self->gui)); } /*********** @@ -195,10 +196,10 @@ void toggle_layer(GtkToggleButton *check, AWeatherGui *gui) ***********/ AWeatherRidge *aweather_ridge_new(AWeatherGui *gui) { - AWeatherRidge *ridge = g_object_new(AWEATHER_TYPE_RIDGE, NULL); - ridge->gui = gui; + AWeatherRidge *self = g_object_new(AWEATHER_TYPE_RIDGE, NULL); + self->gui = gui; - AWeatherView *view = aweather_gui_get_view(gui); + GisView *view = aweather_gui_get_view(gui); GtkWidget *drawing = aweather_gui_get_widget(gui, "drawing"); GtkWidget *config = aweather_gui_get_widget(gui, "tabs"); @@ -211,14 +212,14 @@ AWeatherRidge *aweather_ridge_new(AWeatherGui *gui) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), layers[i].enabled); gtk_box_pack_start(GTK_BOX(hbox), check, FALSE, TRUE, 0); g_object_set_data(G_OBJECT(check), "layer", &layers[i]); - g_signal_connect(check, "toggled", G_CALLBACK(toggle_layer), gui); + g_signal_connect(check, "toggled", G_CALLBACK(toggle_layer), self); } gtk_container_add(GTK_CONTAINER(body), hbox); gtk_notebook_append_page(GTK_NOTEBOOK(config), body, tab); - g_signal_connect(view, "site-changed", G_CALLBACK(on_site_changed), ridge); + g_signal_connect(view, "site-changed", G_CALLBACK(on_site_changed), self); - return ridge; + return self; } static void aweather_ridge_expose(AWeatherPlugin *_ridge) -- 2.43.2