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

Last change on this file since 116 was 116, checked in by sam, 10 years ago

Implement a better timing mechanism for fixed framerate. Accuracy is
sub-millisecond but can be improved if we get rid of SDL timers.

  • Property svn:keywords set to Id
File size: 4.1 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, and show the frame */
81        Video::Clear();
82        Ticker::TickRender();
83        gtk_gl_area_swapbuffers(GTK_GL_AREA(widget));
84        Ticker::ClampFps(FPS);
85    }
86
87    return TRUE;
88}
89
90int main(int argc, char **argv)
91{
92    /* Initialize GTK */
93    g_thread_init(NULL);
94    gtk_init(&argc, &argv);
95
96    if (gdk_gl_query() == FALSE)
97    {
98        g_print("OpenGL not supported\n");
99        return EXIT_FAILURE;
100    }
101
102    GtkBuilder *builder = gtk_builder_new();
103    if (!gtk_builder_add_from_file(builder, "src/gtk/editor.xml", NULL))
104    {
105        g_print("Cannot build from XML\n");
106        return EXIT_FAILURE;
107    }
108
109    /* Create new top level window. */
110    GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
111
112    /* You should always delete gtk_gl_area widgets before exit or else
113       GLX contexts are left undeleted, this may cause problems (=core dump)
114       in some systems.
115       Destroy method of objects is not automatically called on exit.
116       You need to manually enable this feature. Do gtk_quit_add_destroy()
117       for all your top level windows unless you are certain that they get
118       destroy signal by other means.
119    */
120    gtk_quit_add_destroy(1, GTK_OBJECT(window));
121
122    /* Create new OpenGL widget. */
123    int attrlist[] =
124    {
125        GDK_GL_RGBA,
126        GDK_GL_RED_SIZE, 1,
127        GDK_GL_GREEN_SIZE, 1,
128        GDK_GL_BLUE_SIZE, 1,
129        GDK_GL_DOUBLEBUFFER,
130        GDK_GL_NONE
131    };
132
133    GtkWidget *glarea = gtk_gl_area_new(attrlist);
134
135    gtk_widget_set_events(GTK_WIDGET(glarea),
136                          GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
137
138    gtk_signal_connect(GTK_OBJECT(window), "delete_event",
139                       GTK_SIGNAL_FUNC(main_quit), NULL);
140    gtk_signal_connect(GTK_OBJECT(glarea), "expose_event",
141                       GTK_SIGNAL_FUNC(draw), NULL);
142    gtk_signal_connect(GTK_OBJECT(glarea), "configure_event",
143                       GTK_SIGNAL_FUNC(reshape), NULL);
144    gtk_signal_connect(GTK_OBJECT(glarea), "realize",
145                       GTK_SIGNAL_FUNC(init), NULL);
146
147    // Create a scrolled window around our GL widget
148    GtkWidget *sw = GTK_WIDGET(gtk_builder_get_object(builder, "scrolledwindow1"));
149    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), glarea);
150
151    /* Put scrolled window into main window */
152    gtk_widget_show_all(GTK_WIDGET(window));
153
154    // FIXME: detect when the game is killed
155    new Game("maps/testmap.tmx");
156    new DebugFps();
157
158    //gtk_idle_add(tick, glarea);
159    gtk_timeout_add(1000 / FPS, tick, glarea);
160
161    gtk_main();
162
163    return EXIT_SUCCESS;
164}
165
Note: See TracBrowser for help on using the repository browser.