Quellcode durchsuchen

Refactor editor to get the glarea object out of the main source file.

legacy
Sam Hocevar sam vor 14 Jahren
Ursprung
Commit
19170bcac4
5 geänderte Dateien mit 334 neuen und 216 gelöschten Zeilen
  1. +1
    -1
      src/Makefile.am
  2. +11
    -214
      src/gtk/editor.cpp
  3. +16
    -1
      src/gtk/editor.xml
  4. +257
    -0
      src/gtk/glmapview.cpp
  5. +49
    -0
      src/gtk/glmapview.h

+ 1
- 1
src/Makefile.am Datei anzeigen

@@ -18,7 +18,7 @@ test_map_CXXFLAGS = `pkg-config --cflags sdl gl SDL_image`
test_map_LDADD = libcommon.a
test_map_LDFLAGS = `pkg-config --libs sdl gl SDL_image` -lpipi

editor_SOURCES = gtk/editor.cpp
editor_SOURCES = gtk/editor.cpp gtk/glmapview.cpp gtk/glmapview.h
editor_CXXFLAGS = `pkg-config --cflags sdl gl SDL_image gtk+-2.0 gtkgl-2.0`
editor_LDADD = libcommon.a
editor_LDFLAGS = `pkg-config --libs sdl gl gtk+-2.0 gtkgl-2.0 SDL_image`


+ 11
- 214
src/gtk/editor.cpp Datei anzeigen

@@ -7,178 +7,15 @@
# include "config.h"
#endif

#include <cstdio>
#include <cstdlib>
#include <cmath>

#include <gtk/gtk.h>
#include <gtkgl/gtkglarea.h>

#include "core.h"
#include "glmapview.h"
#include "debugfps.h"

static volatile int quit = 0;

static int ticking = 0;
static int panning = 0;
static double xpan = 0.0f, ypan = 0.0f;
static float const FPS = 30.0f;

static MapViewer *mv;
static GtkWidget *glarea;
static GtkAdjustment *hadj, *vadj;

static gint main_quit(GtkWidget *widget, GdkEventExpose *event)
{
(void)widget;
(void)event;

quit = 1;
gtk_main_quit();
return FALSE;
}

static gboolean tick(void *widget)
{
// FIXME: do not do anything if the previous tick was too recent?

// FIXME: only quit if all entities have been cleaned
if (quit)
return FALSE;

ticking = 1;

mv->SetPOV(gtk_adjustment_get_value(hadj), gtk_adjustment_get_value(vadj));

/* Tick the game */
Ticker::TickGame();

gtk_widget_draw(GTK_WIDGET(widget), NULL);

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)
{
/* Manage adjustments */
struct
{
GtkAdjustment *adj;
float map_size, sw_size;
}
s[2] =
{
{ hadj, mv->GetWidth(), widget->allocation.width },
{ vadj, mv->GetHeight(), widget->allocation.height },
};

for (int i = 0; i < 2; i++)
{
gtk_adjustment_set_lower(s[i].adj, 0);
gtk_adjustment_set_upper(s[i].adj, s[i].map_size);
gtk_adjustment_set_step_increment(s[i].adj, 1);
gtk_adjustment_set_page_increment(s[i].adj, s[i].sw_size);
gtk_adjustment_set_page_size(s[i].adj, s[i].sw_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_value_changed(s[i].adj);
}
}

/* Set up display */
if (gtk_gl_area_make_current(GTK_GL_AREA(widget)))
Video::Setup(widget->allocation.width, widget->allocation.height);

return TRUE;
}

static gint reshape(GtkWidget *widget, GdkEventConfigure *event)
{
(void)event;

return init(widget);
}

static gint draw(GtkWidget *widget, GdkEventExpose *event)
{
if (event->count > 0)
return TRUE;

/* OpenGL functions can be called only if make_current returns true */
if (ticking && gtk_gl_area_make_current(GTK_GL_AREA(widget)))
{
ticking = 0;

/* Clear the screen, tick the renderer, show the frame and
* clamp to desired framerate */
Video::Clear();
Ticker::TickDraw();
gtk_gl_area_swapbuffers(GTK_GL_AREA(widget));
while (g_main_context_iteration(NULL, FALSE))
;
Ticker::ClampFps(1000.0f / FPS);
}

return TRUE;
}

int main(int argc, char **argv)
{
/* Initialize GTK */
@@ -191,69 +28,29 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}

/* Build the application interface and keep a few member pointers */
/* Build the application interface */
GtkBuilder *builder = gtk_builder_new();
if (!gtk_builder_add_from_file(builder, "src/gtk/editor.xml", NULL))
{
g_print("Cannot build from XML\n");
return EXIT_FAILURE;
}
gtk_builder_connect_signals(builder, NULL);

GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
GtkWidget *viewport = GTK_WIDGET(
gtk_builder_get_object(builder, "viewport1"));
hadj = gtk_range_get_adjustment(GTK_RANGE(
gtk_builder_get_object(builder, "hscrollbar1")));
vadj = gtk_range_get_adjustment(GTK_RANGE(
gtk_builder_get_object(builder, "vscrollbar1")));
g_object_unref(G_OBJECT(builder));
/* Add our custom GL map viewer */
GlMapView *glmapview = new GlMapView(builder);

/* Create new OpenGL widget */
int attrlist[] =
{
GDK_GL_RGBA,
GDK_GL_RED_SIZE, 1,
GDK_GL_GREEN_SIZE, 1,
GDK_GL_BLUE_SIZE, 1,
GDK_GL_DOUBLEBUFFER,
GDK_GL_NONE
};

glarea = gtk_gl_area_new(attrlist);
gtk_widget_set_usize(glarea, 400, 300);
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);

/* 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 */
gtk_signal_connect(GTK_OBJECT(window), "delete_event",
GTK_SIGNAL_FUNC(main_quit), NULL);

gtk_signal_connect(GTK_OBJECT(glarea), "expose_event",
GTK_SIGNAL_FUNC(draw), NULL);
gtk_signal_connect(GTK_OBJECT(glarea), "configure_event",
GTK_SIGNAL_FUNC(reshape), NULL);
gtk_signal_connect(GTK_OBJECT(glarea), "realize",
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);
/* Show window. We're good to go! */
gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(builder, "window1")));
g_object_unref(G_OBJECT(builder));

// FIXME: detect when the map viewer is killed
mv = new MapViewer("maps/testmap.tmx");
new DebugFps();
glmapview->LoadMap("maps/testmap.tmx");

gtk_widget_show_all(window);
gtk_main();

delete glmapview;

return EXIT_SUCCESS;
}


+ 16
- 1
src/gtk/editor.xml Datei anzeigen

@@ -4,6 +4,7 @@
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="window1">
<property name="title" translatable="yes">Deus Hax Editor</property>
<signal name="delete_event" handler="gtk_main_quit"/>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
@@ -160,6 +161,7 @@
<child>
<object class="GtkHScrollbar" id="hscrollbar1">
<property name="visible">True</property>
<property name="adjustment">gl_hadj</property>
</object>
<packing>
<property name="top_attach">1</property>
@@ -171,6 +173,7 @@
<object class="GtkVScrollbar" id="vscrollbar1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="adjustment">gl_vadj</property>
</object>
<packing>
<property name="left_attach">1</property>
@@ -179,7 +182,7 @@
</packing>
</child>
<child>
<object class="GtkViewport" id="viewport1">
<object class="GtkViewport" id="gl_container">
<property name="visible">True</property>
<property name="resize_mode">queue</property>
<child>
@@ -229,4 +232,16 @@
</object>
</child>
</object>
<object class="GtkAdjustment" id="gl_hadj">
<property name="upper">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
<property name="page_size">10</property>
</object>
<object class="GtkAdjustment" id="gl_vadj">
<property name="upper">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
<property name="page_size">10</property>
</object>
</interface>

+ 257
- 0
src/gtk/glmapview.cpp Datei anzeigen

@@ -0,0 +1,257 @@
//
// Deus Hax (working title)
// Copyright (c) 2010 Sam Hocevar <sam@hocevar.net>
//

#if defined HAVE_CONFIG_H
# include "config.h"
#endif

#include <gtk/gtk.h>
#include <gtkgl/gtkglarea.h>

#include "core.h"
#include "glmapview.h"

static float const FPS = 30.0f;

GlMapView::GlMapView(GtkBuilder *builder)
: hadj(GTK_ADJUSTMENT(gtk_builder_get_object(builder, "gl_hadj"))),
vadj(GTK_ADJUSTMENT(gtk_builder_get_object(builder, "gl_vadj"))),
ticking(FALSE), panning(FALSE),
mapviewer(0),
xpan(0.0), ypan(0.0)
{
/* Create new OpenGL widget */
int attrlist[] =
{
GDK_GL_RGBA,
GDK_GL_RED_SIZE, 1,
GDK_GL_GREEN_SIZE, 1,
GDK_GL_BLUE_SIZE, 1,
GDK_GL_DOUBLEBUFFER,
GDK_GL_NONE
};

glarea = gtk_gl_area_new(attrlist);
gtk_widget_set_usize(glarea, 400, 300);
gtk_widget_set_events(glarea, GDK_EXPOSURE_MASK |
GDK_POINTER_MOTION_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK);
GtkContainer *cont = GTK_CONTAINER(gtk_builder_get_object(builder,
"gl_container"));
gtk_container_add(cont, 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. */
g_idle_add((GSourceFunc)IdleTickSignal, this);

gtk_signal_connect(GTK_OBJECT(glarea), "realize",
GTK_SIGNAL_FUNC(SetupSignal), this);
gtk_signal_connect(GTK_OBJECT(glarea), "destroy",
GTK_SIGNAL_FUNC(DestroySignal), this);
gtk_signal_connect(GTK_OBJECT(glarea), "expose_event",
GTK_SIGNAL_FUNC(DrawSignal), this);
gtk_signal_connect(GTK_OBJECT(glarea), "configure_event",
GTK_SIGNAL_FUNC(ReshapeSignal), this);

gtk_signal_connect(GTK_OBJECT(glarea), "button_press_event",
GTK_SIGNAL_FUNC(MouseButtonSignal), this);
gtk_signal_connect(GTK_OBJECT(glarea), "button_release_event",
GTK_SIGNAL_FUNC(MouseButtonSignal), this);
gtk_signal_connect(GTK_OBJECT(glarea), "motion_notify_event",
GTK_SIGNAL_FUNC(MouseMotionSignal), this);
}

void GlMapView::LoadMap(char const *path)
{
// FIXME: detect when the map viewer is killed
mapviewer = new MapViewer(path);
}

gboolean GlMapView::IdleTick()
{
// FIXME: do not do anything if the previous tick was too recent?

ticking = TRUE;

if (mapviewer)
mapviewer->SetPOV(gtk_adjustment_get_value(hadj),
gtk_adjustment_get_value(vadj));

/* Tick the game */
Ticker::TickGame();

gtk_widget_draw(GTK_WIDGET(glarea), NULL);

return TRUE;
}

gboolean GlMapView::Setup()
{
if (mapviewer)
{
/* Manage adjustments */
struct { GtkAdjustment *adj; float map_size, sw_size; } s[2] =
{
{ hadj, mapviewer->GetWidth(), glarea->allocation.width },
{ vadj, mapviewer->GetHeight(), glarea->allocation.height },
};

for (int i = 0; i < 2; i++)
{
gtk_adjustment_set_lower(s[i].adj, 0);
gtk_adjustment_set_upper(s[i].adj, s[i].map_size);
gtk_adjustment_set_step_increment(s[i].adj, 1);
gtk_adjustment_set_page_increment(s[i].adj, s[i].sw_size);
gtk_adjustment_set_page_size(s[i].adj, s[i].sw_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_value_changed(s[i].adj);
}
}
}

/* Set up display */
if (gtk_gl_area_make_current(GTK_GL_AREA(glarea)))
Video::Setup(glarea->allocation.width, glarea->allocation.height);

return TRUE;
}

gboolean GlMapView::Destroy()
{
g_idle_remove_by_data(this);
return TRUE;
}

gboolean GlMapView::Draw(GdkEventExpose *event)
{
if (event->count > 0)
return TRUE;

/* OpenGL functions can be called only if make_current returns true */
if (ticking && gtk_gl_area_make_current(GTK_GL_AREA(glarea)))
{
ticking = FALSE;

/* Clear the screen, tick the renderer, show the frame and
* clamp to desired framerate */
Video::Clear();
Ticker::TickDraw();
gtk_gl_area_swapbuffers(GTK_GL_AREA(glarea));
while (g_main_context_iteration(NULL, FALSE))
;
Ticker::ClampFps(1000.0f / FPS);
}

return TRUE;
}

gboolean GlMapView::MouseButton(GdkEventButton *event)
{
if (event->type == GDK_BUTTON_PRESS && event->button == 2)
{
panning = TRUE;
xpan = event->x;
ypan = event->y;
GdkCursor *cursor = gdk_cursor_new(GDK_HAND1);
gdk_window_set_cursor(glarea->window, cursor);
gdk_cursor_unref(cursor);
return FALSE;
}
else if (event->type == GDK_BUTTON_RELEASE && event->button == 2)
{
panning = FALSE;
gdk_window_set_cursor(glarea->window, NULL);
return FALSE;
}

return TRUE;
}

gboolean GlMapView::MouseMotion(GdkEventMotion *event)
{
if (panning)
{
if (event->x != xpan)
{
double val = gtk_adjustment_get_value(hadj);
int map_width = mapviewer->GetWidth();
val += xpan - event->x;
xpan = event->x;
if (val + glarea->allocation.width > map_width)
val = map_width - glarea->allocation.width;
gtk_adjustment_set_value(hadj, val);
gtk_adjustment_value_changed(hadj);
}

if (event->y != ypan)
{
double val = gtk_adjustment_get_value(vadj);
int map_height = mapviewer->GetHeight();
val += ypan - event->y;
ypan = event->y;
if (val + glarea->allocation.height > map_height)
val = map_height - glarea->allocation.height;
gtk_adjustment_set_value(vadj, val);
gtk_adjustment_value_changed(vadj);
}
}

return TRUE;
}

/* Private signal slots */
gboolean GlMapView::IdleTickSignal(GlMapView *that)
{
return that->IdleTick();
}

gboolean GlMapView::SetupSignal(GtkWidget *w, GlMapView *that)
{
(void)w;
return that->Setup();
}

gboolean GlMapView::DestroySignal(GtkWidget *w, GlMapView *that)
{
(void)w;
return that->Destroy();
}

gboolean GlMapView::DrawSignal(GtkWidget *w, GdkEventExpose *event,
GlMapView *that)
{
(void)w;
return that->Draw(event);
}

gboolean GlMapView::ReshapeSignal(GtkWidget *w, GdkEventConfigure *event,
GlMapView *that)
{
(void)w;
(void)event;
return that->Setup();
}

gboolean GlMapView::MouseButtonSignal(GtkWidget *w, GdkEventButton *event,
GlMapView *that)
{
(void)w;
return that->MouseButton(event);
}

gboolean GlMapView::MouseMotionSignal(GtkWidget *w, GdkEventMotion *event,
GlMapView *that)
{
(void)w;
return that->MouseMotion(event);
}


+ 49
- 0
src/gtk/glmapview.h Datei anzeigen

@@ -0,0 +1,49 @@
//
// Deus Hax (working title)
// Copyright (c) 2010 Sam Hocevar <sam@hocevar.net>
//

#if !defined __DH_GLMAPVIEW_H__
#define __DH_GLMAPVIEW_H__

#include <gtk/gtk.h>

class GlMapView
{
public:
GlMapView(GtkBuilder *builder);
void LoadMap(char const *path);

private:
/* Private methods */
gboolean IdleTick();
gboolean Setup();
gboolean Destroy();
gboolean Draw(GdkEventExpose *event);
gboolean MouseButton(GdkEventButton *event);
gboolean MouseMotion(GdkEventMotion *event);

/* Private signal slots */
static gboolean IdleTickSignal(GlMapView *that);
static gboolean SetupSignal(GtkWidget *w, GlMapView *that);
static gboolean DestroySignal(GtkWidget *w, GlMapView *that);
static gboolean DrawSignal(GtkWidget *w, GdkEventExpose *event,
GlMapView *that);
static gboolean ReshapeSignal(GtkWidget *w, GdkEventConfigure *event,
GlMapView *that);
static gboolean MouseButtonSignal(GtkWidget *w, GdkEventButton *event,
GlMapView *that);
static gboolean MouseMotionSignal(GtkWidget *w, GdkEventMotion *event,
GlMapView *that);

private:
GtkAdjustment *hadj, *vadj;
GtkWidget *glarea;
gboolean ticking, panning;

MapViewer *mapviewer;
double xpan, ypan;
};

#endif // __DH_GLMAPVIEW_H__


Laden…
Abbrechen
Speichern