Permalink
Browse files

Create our own GL widget instead of using gtkglext which hasn't been …

…ported to Gtk3 yet
  • Loading branch information...
Kazade committed May 7, 2012
1 parent 61f0296 commit d97d7628d421adf8a8b03f92b92740f53fa8f054
@@ -185,7 +185,7 @@ void EditorView::do_scroll(GdkEventScroll* event)
if(zoom_ <= 0.2f) zoom_ = 0.2f;
- MakeCurrent context(this);
+ if(!make_current()) return;
do_resize(get_widget()->get_width(), get_widget()->get_height());
}
@@ -203,10 +203,7 @@ void EditorView::do_button_press(GdkEventButton* event)
if(event->button == 1) {
//Select the tile instance under the cursor
- MakeCurrent context(this);
- if(!context.ok) {
- return;
- }
+
assert(picker_);
@@ -229,7 +226,8 @@ void EditorView::do_button_press(GdkEventButton* event)
//Spawn a new tile instance
//Get the spawn position (where we clicked
- MakeCurrent context(this);
+ if(!make_current()) return;
+
kmVec2 pos = unproject(event->x, event->y);
//Snap the position to the grid
grid_->snap_to(pos.x, pos.y);
@@ -243,10 +241,7 @@ void EditorView::do_button_press(GdkEventButton* event)
}
} else if (event->button == 3) {
//Delete the instance under the cursor
- MakeCurrent context(this);
- if(!context.ok) {
- return;
- }
+ if(!make_current()) return;
gfloat x = event->x;
gfloat y = event->y;
@@ -279,10 +274,7 @@ void EditorView::do_motion(GdkEventMotion* event)
*/
if(active_object_ && event->state & GDK_BUTTON1_MASK && active_timer_.elapsed() >= 0.2) {
- MakeCurrent context(this);
- if(!context.ok) {
- return;
- }
+ if(!make_current()) return;
kmVec2 pos = unproject(event->x, event->y);
grid_->snap_to(pos.x, pos.y);
@@ -0,0 +1,128 @@
+#include "gtk_gl_widget.h"
+
+const int attributes[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER, True,
+ GLX_DEPTH_SIZE, 24,
+ None
+};
+
+static XVisualInfo *
+gdk_x11_visual_get_xvinfo (GdkScreen *screen,
+ GdkVisual *visual)
+{
+ Display *xdisplay;
+ XVisualInfo xvinfo_template;
+ XVisualInfo *xvinfo_list;
+ int nitems_return;
+
+ xdisplay = GDK_SCREEN_XDISPLAY (screen);
+ xvinfo_template.visualid = XVisualIDFromVisual (GDK_VISUAL_XVISUAL (visual));
+ xvinfo_template.screen = GDK_SCREEN_XNUMBER (screen);
+
+ xvinfo_list = XGetVisualInfo (xdisplay,
+ VisualIDMask | VisualScreenMask,
+ &xvinfo_template,
+ &nitems_return);
+
+ /* Returned XVisualInfo needs to be unique */
+ g_assert (xvinfo_list != NULL && nitems_return == 1);
+
+ return xvinfo_list;
+}
+
+GtkGLWidget::GtkGLWidget(Gtk::DrawingArea* area):
+ area_(area) {
+
+ area_->set_double_buffered(false);
+
+ Glib::RefPtr<Gdk::Display> display = Gdk::Display::get_default();
+ Glib::RefPtr<Gdk::Screen> screen = display->get_default_screen();
+ Glib::RefPtr<Gdk::Visual> visual = screen->get_rgba_visual();
+ Glib::RefPtr<Gdk::Colormap> colourmap = Gdk::Colormap::create(visual, false);
+
+ area->set_colormap(colourmap);
+
+ Display* xdisplay = GDK_DISPLAY_XDISPLAY(display->gobj());
+
+ context_ = glXCreateContext (xdisplay, gdk_x11_visual_get_xvinfo(screen->gobj(), visual->gobj()), NULL, TRUE);
+
+ area_->add_events(
+ Gdk::EXPOSURE_MASK |
+ Gdk::BUTTON_PRESS_MASK |
+ Gdk::BUTTON_RELEASE_MASK |
+ Gdk::POINTER_MOTION_MASK |
+ Gdk::POINTER_MOTION_HINT_MASK |
+ Gdk::KEY_PRESS_MASK |
+ Gdk::KEY_RELEASE_MASK
+ );
+
+ area_->signal_realize().connect(sigc::mem_fun(this, &GtkGLWidget::on_area_realize));
+ //area_->signal_draw().connect(sigc::mem_fun(this, &GtkGLWidget::on_area_draw));
+ area_->signal_expose_event().connect(sigc::mem_fun(this, &GtkGLWidget::on_area_expose));
+ area_->signal_configure_event().connect(sigc::mem_fun(this, &GtkGLWidget::on_area_configure));
+ idle_connection_ = Glib::signal_timeout().connect(sigc::mem_fun(this, &GtkGLWidget::on_area_idle), 10);
+}
+
+bool GtkGLWidget::make_current() {
+ Glib::RefPtr<Gdk::Window> window = area_->get_window();
+ Display* xdisplay = gdk_x11_drawable_get_xdisplay(window->gobj());
+ int id = gdk_x11_drawable_get_xid(window->gobj());
+ return glXMakeCurrent(xdisplay, id, context_) == TRUE;
+}
+
+bool GtkGLWidget::on_area_idle() {
+ area_->queue_draw();
+ return true;
+}
+
+void GtkGLWidget::on_area_realize() {
+ if(make_current()) {
+ glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
+ glEnable (GL_DEPTH_TEST);
+ glDepthFunc (GL_LEQUAL);
+ glEnable (GL_CULL_FACE);
+ glCullFace (GL_BACK);
+ glDisable (GL_DITHER);
+ glShadeModel (GL_SMOOTH);
+
+ do_init();
+ }
+}
+
+/*
+bool GtkGLWidget::on_area_draw(const ::Cairo::RefPtr< ::Cairo::Context>& cr) {
+
+
+ return true;
+}
+
+*/
+bool GtkGLWidget::on_area_expose(GdkEventExpose *event) {
+ if(event->count > 0) return true;
+
+ if(make_current()) {
+ Glib::RefPtr<Gdk::Window> window = area_->get_window();
+ Display* xdisplay = gdk_x11_drawable_get_xdisplay(window->gobj());
+ int id = gdk_x11_drawable_get_xid(window->gobj());
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ do_render();
+
+ glXSwapBuffers(xdisplay, id);
+ }
+
+ return true;
+}
+
+bool GtkGLWidget::on_area_configure(GdkEventConfigure* event) {
+ Gtk::Allocation allocation = area_->get_allocation();
+ if(make_current()) {
+ glViewport (0, 0, allocation.get_width(), allocation.get_height());
+ do_resize(allocation.get_width(), allocation.get_height());
+ }
+ return true;
+}
@@ -0,0 +1,43 @@
+#ifndef GTK_GL_WIDGET_H
+#define GTK_GL_WIDGET_H
+
+#include <gtkmm.h>
+#include <tr1/memory>
+
+#include <GL/glx.h>
+#include <gdk/gdkx.h>
+
+class GtkGLWidget {
+public:
+ typedef std::tr1::shared_ptr<GtkGLWidget> ptr;
+
+ GtkGLWidget(Gtk::DrawingArea* area);
+ virtual ~GtkGLWidget() {
+ if(idle_connection_.connected()) {
+ idle_connection_.disconnect();
+ }
+ }
+
+ Gtk::DrawingArea* area() { return area_; }
+ Gtk::DrawingArea* get_widget() { return area(); }
+
+ void on_area_realize();
+ //bool on_area_draw(const ::Cairo::RefPtr< ::Cairo::Context>& cr);
+
+ bool on_area_expose(GdkEventExpose *event);
+ bool on_area_configure(GdkEventConfigure* event);
+ bool on_area_idle();
+
+protected:
+ bool make_current();
+
+ virtual void do_render() {}
+ virtual void do_init() {}
+ virtual void do_resize(int width, int height) {}
+private:
+ Gtk::DrawingArea* area_;
+ GLXContext context_;
+ sigc::connection idle_connection_;
+};
+
+#endif
@@ -48,6 +48,8 @@ MainWindow::MainWindow():
void MainWindow::create_widgets() {
Glib::RefPtr<Gtk::Builder> builder = Gtk::Builder::create();
+
+ Gtk::DrawingArea* canvas = nullptr;
//Just let exceptions propagate - we can't do anything about them anyway
builder->add_from_file(UI_FILE);
@@ -59,18 +61,23 @@ void MainWindow::create_widgets() {
builder->get_widget("redo_toolbutton", gtk_redo_toolbutton_);
builder->get_widget("add_tile_button", gtk_add_tile_button_);
- builder->get_widget("canvas", gtk_canvas_);
+ builder->get_widget("canvas", canvas);
builder->get_widget("layer_tree_view", gtk_layer_view_);
builder->get_widget("add_layer_button", gtk_add_layer_button_);
builder->get_widget("delete_layer_button", gtk_delete_layer_button_);
builder->get_widget("side_bar_alignment", gtk_side_bar_);
- assert(gtk_canvas_);
- editor_view_.reset(new EditorView(gtk_canvas_, this));
+ gtk_canvas_.reset(new GtkGLWidget(canvas));
+
+ //assert(gtk_canvas_);
+ editor_view_.reset(new EditorView(gtk_canvas_->area(), this));
assert(gtk_tile_selector_canvas_);
selector_.reset(new OpenGLTileSelector(gtk_tile_selector_canvas_));
- editor_view_->set_tile_selector(selector_.get());
+
+ if(editor_view_) {
+ editor_view_->set_tile_selector(selector_.get());
+ }
layer_manager_.reset(new LayerManager(this, gtk_layer_view_, gtk_add_layer_button_, gtk_delete_layer_button_));
@@ -136,7 +143,10 @@ void MainWindow::create_new_level(const std::string& name, uint32_t tile_size) {
level_changed_connection_ = level_->signal_changed().connect(sigc::mem_fun(this, &MainWindow::on_level_changed));
level_saved_connection_ = level_->signal_saved().connect(sigc::mem_fun(this, &MainWindow::on_level_saved));
- editor_view_->set_level(level_.get());
+ if(editor_view_) {
+ editor_view_->set_level(level_.get());
+ }
+
layer_manager_->set_level(level_.get());
}
@@ -33,6 +33,7 @@
#include "editor_view.h"
#include "layer_manager.h"
#include "action_manager.h"
+#include "gtkgl/gtk_gl_widget.h"
class MainWindow {
public:
@@ -73,7 +74,8 @@ class MainWindow {
Gtk::Button* gtk_add_layer_button_;
Gtk::Button* gtk_delete_layer_button_;
- Gtk::DrawingArea* gtk_canvas_, *gtk_tile_selector_canvas_;
+ GtkGLWidget::ptr gtk_canvas_;
+ Gtk::DrawingArea* gtk_tile_selector_canvas_;
Gtk::TreeView* gtk_layer_view_;
void initialize_tile_canvas();
@@ -256,7 +256,7 @@ void OpenGLTileEditorCanvas::do_button_press(GdkEventButton* event)
} else if (event->button == 3) {
//TODO: Only the current layer iterators should be passed to pick() otherwise we'll get
//false positives
- MakeCurrent context(this);
+ make_current();
Tile::GeometryIteratorPair iters = parent_->get_tile()->get_geometry_iterators();
GeometryElement::ptr elem = picker_->pick(event->x, event->y, iters.first, iters.second);
@@ -76,7 +76,7 @@ void OpenGLTileSelector::do_render()
glDepthFunc(GL_LEQUAL);
float ytrans = 0.0f;
- if(Gtk::ScrolledWindow* scr = dynamic_cast<Gtk::ScrolledWindow*>(get_widget()->get_parent())) {
+ if(Gtk::ScrolledWindow* scr = dynamic_cast<Gtk::ScrolledWindow*>(area()->get_parent())) {
ytrans = scr->get_vadjustment()->get_value();
}
@@ -164,7 +164,7 @@ GLuint OpenGLTileSelector::get_texture_for_tile(Tile* tile)
*/
void OpenGLTileSelector::do_scroll(GdkEventScroll* event)
{
- if(Gtk::ScrolledWindow* scr = dynamic_cast<Gtk::ScrolledWindow*>(get_widget()->get_parent())) {
+ if(Gtk::ScrolledWindow* scr = dynamic_cast<Gtk::ScrolledWindow*>(area()->get_parent())) {
gdouble val = scr->get_vadjustment()->get_value();
if(event->direction == GDK_SCROLL_UP) {
@@ -190,10 +190,7 @@ void OpenGLTileSelector::do_button_press(GdkEventButton* event)
}
if(event->type == GDK_BUTTON_PRESS && event->button == 1 && tileset_) {
- MakeCurrent context(this);
- if(!context.ok) {
- return;
- }
+ if(!make_current()) return;
assert(picker_);
@@ -237,7 +234,7 @@ void OpenGLTileSelector::init_tileset()
total_display_height_ = -y;
- if(Gtk::ScrolledWindow* scr = dynamic_cast<Gtk::ScrolledWindow*>(get_widget()->get_parent())) {
+ if(Gtk::ScrolledWindow* scr = dynamic_cast<Gtk::ScrolledWindow*>(area()->get_parent())) {
scr->get_vadjustment()->set_upper(total_display_height_ + 1.0f);
scr->get_vadjustment()->set_value(0);
}
@@ -257,7 +254,7 @@ void OpenGLTileSelector::on_tile_edit()
tile_editor_.reset(new OpenGLTileEditor(tile.get()));
- if(tile_editor_->run(dynamic_cast<Gtk::Window*>(get_widget()->get_toplevel())) == Gtk::RESPONSE_OK) {
+ if(tile_editor_->run(dynamic_cast<Gtk::Window*>(area()->get_toplevel())) == Gtk::RESPONSE_OK) {
tile->save();
}
}
Oops, something went wrong.

0 comments on commit d97d762

Please sign in to comment.