source: trunk/src/gtk/editor.cpp @ 124

Last change on this file since 124 was 124, checked in by sam, 11 years ago

Make the editor more responsive by handling GTK events before waiting for
the loop to complete.

  • Property svn:keywords set to Id
File size: 4.2 KB
Line 
1//
2// Deus Hax (working title)
3// Copyright (c) 2010 Sam Hocevar <sam@hocevar.net>
4//
5
6#if defined HAVE_CONFIG_H
7#   include "config.h"
8#endif
9
10#include <cstdio>
11#include <cstdlib>
12#include <cmath>
13
14#include <gtk/gtk.h>
15#include <gtkgl/gtkglarea.h>
16
17#include "ticker.h"
18#include "debugfps.h"
19#include "video.h"
20#include "game.h"
21
22static volatile int quit = 0;
23
24static int ticking = 0;
25static float const FPS = 30.0f;
26
27static gint main_quit(GtkWidget *widget, GdkEventExpose *event)
28{
29    (void)widget;
30    (void)event;
31
32    quit = 1;
33    gtk_main_quit();
34    return FALSE;
35}
36
37static gboolean tick(void *widget)
38{
39    // FIXME: do not do anything if the previous tick was too recent?
40
41    // FIXME: only quit if all assets have been cleaned
42    if (quit)
43        return FALSE;
44
45    ticking = 1;
46
47    /* Tick the game */
48    Ticker::TickGame();
49
50    gtk_widget_draw(GTK_WIDGET(widget), NULL);
51
52    return TRUE;
53}
54
55static gint init(GtkWidget *widget)
56{
57    if (gtk_gl_area_make_current(GTK_GL_AREA(widget)))
58        Video::Setup(widget->allocation.width, widget->allocation.height);
59
60    return TRUE;
61}
62
63static gint reshape(GtkWidget *widget, GdkEventConfigure *event)
64{
65    (void)event;
66
67    return init(widget);
68}
69
70static gint draw(GtkWidget *widget, GdkEventExpose *event)
71{
72    if (event->count > 0)
73        return TRUE;
74
75    /* OpenGL functions can be called only if make_current returns true */
76    if (ticking && gtk_gl_area_make_current(GTK_GL_AREA(widget)))
77    {
78        ticking = 0;
79
80        /* Clear the screen, tick the renderer, show the frame and
81         * clamp to desired framerate. */
82        Video::Clear();
83        Ticker::TickRender();
84        gtk_gl_area_swapbuffers(GTK_GL_AREA(widget));
85        while (g_main_context_iteration(NULL, FALSE))
86            ;
87        Ticker::ClampFps(FPS);
88    }
89
90    return TRUE;
91}
92
93int main(int argc, char **argv)
94{
95    /* Initialize GTK */
96    g_thread_init(NULL);
97    gtk_init(&argc, &argv);
98
99    if (gdk_gl_query() == FALSE)
100    {
101        g_print("OpenGL not supported\n");
102        return EXIT_FAILURE;
103    }
104
105    GtkBuilder *builder = gtk_builder_new();
106    if (!gtk_builder_add_from_file(builder, "src/gtk/editor.xml", NULL))
107    {
108        g_print("Cannot build from XML\n");
109        return EXIT_FAILURE;
110    }
111
112    /* Create new top level window. */
113    GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
114
115    /* You should always delete gtk_gl_area widgets before exit or else
116       GLX contexts are left undeleted, this may cause problems (=core dump)
117       in some systems.
118       Destroy method of objects is not automatically called on exit.
119       You need to manually enable this feature. Do gtk_quit_add_destroy()
120       for all your top level windows unless you are certain that they get
121       destroy signal by other means.
122    */
123    gtk_quit_add_destroy(1, GTK_OBJECT(window));
124
125    /* Create new OpenGL widget. */
126    int attrlist[] =
127    {
128        GDK_GL_RGBA,
129        GDK_GL_RED_SIZE, 1,
130        GDK_GL_GREEN_SIZE, 1,
131        GDK_GL_BLUE_SIZE, 1,
132        GDK_GL_DOUBLEBUFFER,
133        GDK_GL_NONE
134    };
135
136    GtkWidget *glarea = gtk_gl_area_new(attrlist);
137
138    gtk_widget_set_events(GTK_WIDGET(glarea),
139                          GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
140
141    gtk_signal_connect(GTK_OBJECT(window), "delete_event",
142                       GTK_SIGNAL_FUNC(main_quit), NULL);
143    gtk_signal_connect(GTK_OBJECT(glarea), "expose_event",
144                       GTK_SIGNAL_FUNC(draw), NULL);
145    gtk_signal_connect(GTK_OBJECT(glarea), "configure_event",
146                       GTK_SIGNAL_FUNC(reshape), NULL);
147    gtk_signal_connect(GTK_OBJECT(glarea), "realize",
148                       GTK_SIGNAL_FUNC(init), NULL);
149
150    // Create a scrolled window around our GL widget
151    GtkWidget *sw = GTK_WIDGET(gtk_builder_get_object(builder, "scrolledwindow1"));
152    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), glarea);
153
154    /* Put scrolled window into main window */
155    gtk_widget_show_all(GTK_WIDGET(window));
156
157    // FIXME: detect when the game is killed
158    new Game("maps/testmap.tmx");
159    new DebugFps();
160
161    /* We tick from the idle function instead of a timeout to avoid
162     * stealing time from the GTK loop. */
163    gtk_idle_add(tick, glarea);
164    gtk_main();
165
166    return EXIT_SUCCESS;
167}
168
Note: See TracBrowser for help on using the repository browser.