| @@ -20,6 +20,8 @@ | |||||
| static volatile int quit = 0; | static volatile int quit = 0; | ||||
| static int ticking = 0; | static int ticking = 0; | ||||
| static int panning = 0; | |||||
| static double xpan = 0.0f, ypan = 0.0f; | |||||
| static float const FPS = 30.0f; | static float const FPS = 30.0f; | ||||
| static MapViewer *mv; | static MapViewer *mv; | ||||
| @@ -56,8 +58,63 @@ static gboolean tick(void *widget) | |||||
| return TRUE; | return TRUE; | ||||
| } | } | ||||
| static gboolean mouse_button(GtkWidget *widget, GdkEventButton *event, | |||||
| gpointer user_data) | |||||
| { | |||||
| if (event->type == GDK_BUTTON_PRESS && event->button == 2) | |||||
| { | |||||
| panning = 1; | |||||
| xpan = event->x; | |||||
| ypan = event->y; | |||||
| GdkCursor *cursor = gdk_cursor_new(GDK_HAND1); | |||||
| gdk_window_set_cursor(widget->window, cursor); | |||||
| gdk_cursor_unref(cursor); | |||||
| return FALSE; | |||||
| } | |||||
| else if (event->type == GDK_BUTTON_RELEASE && event->button == 2) | |||||
| { | |||||
| panning = 0; | |||||
| gdk_window_set_cursor(widget->window, NULL); | |||||
| return FALSE; | |||||
| } | |||||
| return TRUE; | |||||
| } | |||||
| static gboolean mouse_motion(GtkWidget *widget, GdkEventMotion *event, | |||||
| gpointer user_data) | |||||
| { | |||||
| if (panning) | |||||
| { | |||||
| if (event->x != xpan) | |||||
| { | |||||
| double val = gtk_adjustment_get_value(hadj); | |||||
| val += xpan - event->x; | |||||
| xpan = event->x; | |||||
| if (val + widget->allocation.width > mv->GetWidth()) | |||||
| val = mv->GetWidth() - widget->allocation.width; | |||||
| gtk_adjustment_set_value(hadj, val); | |||||
| gtk_adjustment_value_changed(hadj); | |||||
| } | |||||
| if (event->y != ypan) | |||||
| { | |||||
| double val = gtk_adjustment_get_value(vadj); | |||||
| val += ypan - event->y; | |||||
| ypan = event->y; | |||||
| if (val + widget->allocation.height > mv->GetHeight()) | |||||
| val = mv->GetHeight() - widget->allocation.height; | |||||
| gtk_adjustment_set_value(vadj, val); | |||||
| gtk_adjustment_value_changed(vadj); | |||||
| } | |||||
| } | |||||
| return TRUE; | |||||
| } | |||||
| static gint init(GtkWidget *widget) | static gint init(GtkWidget *widget) | ||||
| { | { | ||||
| /* Manage adjustments */ | |||||
| struct | struct | ||||
| { | { | ||||
| GtkAdjustment *adj; | GtkAdjustment *adj; | ||||
| @@ -77,21 +134,22 @@ static gint init(GtkWidget *widget) | |||||
| gtk_adjustment_set_page_increment(s[i].adj, s[i].sw_size); | gtk_adjustment_set_page_increment(s[i].adj, s[i].sw_size); | ||||
| gtk_adjustment_set_page_size(s[i].adj, s[i].sw_size); | gtk_adjustment_set_page_size(s[i].adj, s[i].sw_size); | ||||
| float hval = gtk_adjustment_get_value(s[i].adj); | |||||
| if (hval + s[i].sw_size > s[i].map_size) | |||||
| float val = gtk_adjustment_get_value(s[i].adj); | |||||
| if (val + s[i].sw_size > s[i].map_size) | |||||
| { | { | ||||
| gtk_adjustment_set_value(s[i].adj, s[i].map_size - s[i].sw_size); | gtk_adjustment_set_value(s[i].adj, s[i].map_size - s[i].sw_size); | ||||
| gtk_adjustment_value_changed(s[i].adj); | gtk_adjustment_value_changed(s[i].adj); | ||||
| } | } | ||||
| } | } | ||||
| /* Set up display */ | |||||
| if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) | if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) | ||||
| Video::Setup(widget->allocation.width, widget->allocation.height); | Video::Setup(widget->allocation.width, widget->allocation.height); | ||||
| return TRUE; | return TRUE; | ||||
| } | } | ||||
| static gint reshape_gl(GtkWidget *widget, GdkEventConfigure *event) | |||||
| static gint reshape(GtkWidget *widget, GdkEventConfigure *event) | |||||
| { | { | ||||
| (void)event; | (void)event; | ||||
| @@ -163,9 +221,15 @@ int main(int argc, char **argv) | |||||
| glarea = gtk_gl_area_new(attrlist); | glarea = gtk_gl_area_new(attrlist); | ||||
| gtk_widget_set_usize(glarea, 400, 300); | gtk_widget_set_usize(glarea, 400, 300); | ||||
| gtk_widget_set_events(glarea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK); | |||||
| gtk_widget_set_events(glarea, GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | |||||
| | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); | |||||
| gtk_container_add(GTK_CONTAINER(viewport), glarea); | gtk_container_add(GTK_CONTAINER(viewport), glarea); | ||||
| /* We tick from the idle function instead of a timeout to avoid | |||||
| * stealing time from the GTK loop when the callback time exceeds | |||||
| * the timeout value. */ | |||||
| gtk_idle_add(tick, glarea); | |||||
| /* Connect signals and show window */ | /* Connect signals and show window */ | ||||
| gtk_signal_connect(GTK_OBJECT(window), "delete_event", | gtk_signal_connect(GTK_OBJECT(window), "delete_event", | ||||
| GTK_SIGNAL_FUNC(main_quit), NULL); | GTK_SIGNAL_FUNC(main_quit), NULL); | ||||
| @@ -173,19 +237,21 @@ int main(int argc, char **argv) | |||||
| gtk_signal_connect(GTK_OBJECT(glarea), "expose_event", | gtk_signal_connect(GTK_OBJECT(glarea), "expose_event", | ||||
| GTK_SIGNAL_FUNC(draw), NULL); | GTK_SIGNAL_FUNC(draw), NULL); | ||||
| gtk_signal_connect(GTK_OBJECT(glarea), "configure_event", | gtk_signal_connect(GTK_OBJECT(glarea), "configure_event", | ||||
| GTK_SIGNAL_FUNC(reshape_gl), NULL); | |||||
| GTK_SIGNAL_FUNC(reshape), NULL); | |||||
| gtk_signal_connect(GTK_OBJECT(glarea), "realize", | gtk_signal_connect(GTK_OBJECT(glarea), "realize", | ||||
| GTK_SIGNAL_FUNC(init), NULL); | GTK_SIGNAL_FUNC(init), NULL); | ||||
| gtk_signal_connect(GTK_OBJECT(glarea), "button_press_event", | |||||
| GTK_SIGNAL_FUNC(mouse_button), NULL); | |||||
| gtk_signal_connect(GTK_OBJECT(glarea), "button_release_event", | |||||
| GTK_SIGNAL_FUNC(mouse_button), NULL); | |||||
| gtk_signal_connect(GTK_OBJECT(glarea), "motion_notify_event", | |||||
| GTK_SIGNAL_FUNC(mouse_motion), NULL); | |||||
| // FIXME: detect when the map viewer is killed | // FIXME: detect when the map viewer is killed | ||||
| mv = new MapViewer("maps/testmap.tmx"); | mv = new MapViewer("maps/testmap.tmx"); | ||||
| new DebugFps(); | new DebugFps(); | ||||
| /* We tick from the idle function instead of a timeout to avoid | |||||
| * stealing time from the GTK loop when the callback time exceeds | |||||
| * the timeout value. */ | |||||
| gtk_widget_show_all(window); | gtk_widget_show_all(window); | ||||
| gtk_idle_add(tick, glarea); | |||||
| gtk_main(); | gtk_main(); | ||||
| return EXIT_SUCCESS; | return EXIT_SUCCESS; | ||||