add the update_ux_uy_yz
[hkl.git] / gui / hkl3d-gui-scene.vala
blob68d0c0b161893111339fbbea168ef5fd7518daa1
1 /*
2 * This file is part of the hkl3d library.
3 * inspired from logo-model.c of the GtkGLExt logo models.
4 * written by Naofumi Yasufuku <naofumi@users.sourceforge.net>
6 * The hkl library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * The hkl library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with the hkl library. If not, see <http://www.gnu.org/licenses/>.
19 * Copyright (C) 2010-2011 Synchrotron SOLEIL
20 * L'Orme des Merisiers Saint-Aubin
21 * BP 48 91192 GIF-sur-YVETTE CEDEX
23 * Authors: Oussama Sboui <oussama.sboui@synchrotron-soleil.fr>
24 * Picca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>
27 using Gtk;
28 using Gdk;
29 using GL;
31 public class Hkl3D.Gui.Scene : Gtk.DrawingArea
33 // Invalidate whole window.
34 public void invalidate()
36 this.get_window().invalidate_rect((Gdk.Rectangle)this.allocation, false);
39 // Update window synchronously (fast).
40 public void update()
42 this.get_window().process_updates(false);
45 // timeout signal connection:
46 public signal void m_ConnectionTimeout();
48 // OpenGL scene related methods:
49 public bool BulletDraw_is_enabled()
51 return this.m_Model.bullet;
54 public bool wireframe_is_enabled()
56 return this.m_Model.wireframe;
59 public bool aabbBoxDraw_is_enabled()
61 return this.m_Model.aabb;
64 // Popup menu:
65 private Gtk.Menu m_Menu;
67 // OpenGL scene related objects:
68 Hkl3D.Gui.View m_View;
69 Hkl3D.Gui.ModelDraw m_Model;
71 private static const uint TIMEOUT_INTERVAL = 100000000;
73 private const float CLEAR_COLOR[4] = { 0.9f, 0.8f, 0.6f, 1.0f };
74 private const float CLEAR_DEPTH = 1.0f;
76 private const float LIGHT0_POSITION[4] = { 0.0f, 0.0f, 30.0f, 0.0f };
77 private const float LIGHT0_DIFFUSE[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
78 private const float LIGHT0_SPECULAR[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
80 public Scene(Hkl3D.Anticollision hkl3d,
81 bool enableBulletDraw, bool enableWireframe,
82 bool enableAAbbBoxDraw, bool enableOrthoView)
84 this.m_View = new Hkl3D.Gui.View();
86 this.m_Model = new Hkl3D.Gui.ModelDraw(hkl3d,
87 enableBulletDraw, enableWireframe,
88 enableAAbbBoxDraw, enableOrthoView);
90 Gdk.GLConfig? glconfig = new Gdk.GLConfig.by_mode (Gdk.GLConfigMode.RGB
91 | Gdk.GLConfigMode.DEPTH
92 | Gdk.GLConfigMode.DOUBLE);
94 if (glconfig == null) {
95 stderr.printf("*** Cannot find the double-buffered visual.\n");
96 stderr.printf("*** Trying single-buffered visual.\n");
98 // Try single-buffered visual
99 glconfig = new Gdk.GLConfig.by_mode(Gdk.GLConfigMode.RGB
100 | Gdk.GLConfigMode.DEPTH);
101 if (glconfig == null) {
102 stderr.printf("*** Cannot find any OpenGL-capable visual.\n");
103 //exit(1);
107 // Set OpenGL-capability to the widget.
109 Gtk.WidgetGL.set_gl_capability(this, glconfig, null, true,
110 GLRenderType.RGBA_TYPE);
113 // Add events.
115 this.add_events (Gdk.EventMask.BUTTON_PRESS_MASK
116 | Gdk.EventMask.BUTTON1_MOTION_MASK
117 | Gdk.EventMask.BUTTON2_MOTION_MASK
118 | Gdk.EventMask.VISIBILITY_NOTIFY_MASK);
120 // View transformation signals.
121 //this.button_press_event.connect(m_View.on_button_press_event);
122 //this.motion_notify_event.connect(m_View.on_motion_notify_event);
123 //this.scroll_event.connect(m_View.on_scroll_event);
125 this.m_Menu = this.create_popup_menu();
128 public override void realize()
130 // We need to call the base on_realize()
131 base.realize();
134 // Get GL::Drawable.
136 var gldrawable = Gtk.WidgetGL.get_gl_drawable(this);
139 // GL calls.
141 // *** OpenGL BEGIN ***
142 if (!gldrawable.gl_begin(Gtk.WidgetGL.get_gl_context(this)))
143 return;
145 glClearColor(CLEAR_COLOR[0], CLEAR_COLOR[1], CLEAR_COLOR[2], CLEAR_COLOR[3]);
146 glClearDepth(CLEAR_DEPTH);
148 glLightfv(GL_LIGHT0, GL_POSITION, LIGHT0_POSITION);
149 glLightfv(GL_LIGHT0, GL_DIFFUSE, LIGHT0_DIFFUSE);
150 glLightfv(GL_LIGHT0, GL_SPECULAR, LIGHT0_SPECULAR);
152 glEnable(GL_LIGHTING);
153 glEnable(GL_LIGHT0);
155 glEnable(GL_DEPTH_TEST);
157 glShadeModel(GL_SMOOTH);
159 this.m_Model.draw();
161 gldrawable.gl_end();
162 // *** OpenGL END ***
165 public override bool configure_event(Gdk.EventConfigure event)
168 // Get GL::Drawable.
170 var gldrawable = Gtk.WidgetGL.get_gl_drawable(this);
173 // GL calls.
175 // *** OpenGL BEGIN ***
177 if (!gldrawable.gl_begin(Gtk.WidgetGL.get_gl_context(this)))
178 return false;
180 this.m_View.frustum((GL.GLsizei)this.allocation.width, (GL.GLsizei)this.allocation.height);
181 gldrawable.gl_end();
182 // *** OpenGL END ***
184 return true;
187 public override bool expose_event(Gdk.EventExpose event)
190 // Get GL::Drawable.
192 var gldrawable = Gtk.WidgetGL.get_gl_drawable(this);
195 // GL calls.
197 // *** OpenGL BEGIN ***
198 if (!gldrawable.gl_begin(Gtk.WidgetGL.get_gl_context(this)))
199 return false;
201 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
203 glLoadIdentity();
205 // View transformation.
206 this.m_View.xform();
208 // model.
209 this.m_Model.draw();
211 // Swap buffers.
212 if (gldrawable.is_double_buffered())
213 gldrawable.swap_buffers();
214 else
215 glFlush();
217 gldrawable.gl_end();
218 // *** OpenGL END ***
220 return true;
223 public override bool button_press_event(Gdk.EventButton event)
225 if (event.button == 3) {
226 this.m_Menu.popup(null, null, null, event.button, event.time);
227 return true;
230 // don't block
231 return false;
234 public override bool map_event(Gdk.Event event)
236 if (this.m_Model.bullet)
237 this.timeout_add();
239 return true;
242 public override bool unmap_event(Gdk.Event event)
244 this.timeout_remove();
246 return true;
249 public override bool visibility_notify_event(Gdk.Event event)
251 if (this.m_Model.bullet) {
252 //if (event.state == GDK_VISIBILITY_FULLY_OBSCURED)
254 // this.timeout_add();
256 return true;
259 public bool on_timeout()
261 // Invalidate whole window.
262 this.invalidate();
263 // Update window synchronously (fast).
264 this.update();
266 return true;
269 public void timeout_add()
272 if (!m_ConnectionTimeout.connected())
273 GLib.timeout().connect(this.on_timeout, this.TIMEOUT_INTERVAL);
275 m_ConnectionTimeout = Glib::signal_timeout().connect(
276 sigc::mem_fun(*this, &Scene::on_timeout), TIMEOUT_INTERVAL);
280 public void timeout_remove()
283 if (this.m_ConnectionTimeout.connected())
284 m_ConnectionTimeout.disconnect();
288 public void bulletDraw()
290 if (this.m_Model.bullet) {
291 this.m_Model.bullet = false;
292 this.timeout_remove();
293 }else{
294 this.m_Model.bullet = true;
295 this.timeout_add();
299 public void wireframe_view()
301 this.m_Model.wireframe = !this.m_Model.wireframe;
304 public void orthoView()
306 if (this.m_Model.ortho){
307 this.m_View.frustum((GL.GLsizei)this.allocation.width, (GL.GLsizei)this.allocation.height);
308 this.m_Model.ortho = false;
309 }else{
310 this.m_View.ortho((GL.GLsizei)this.allocation.width, (GL.GLsizei)this.allocation.height);
311 this.m_Model.ortho = true;
315 public void AAbbBoxDraw()
317 if (this.m_Model.aabb) {
318 this.m_Model.aabb = false;
319 if (this.m_Model.bullet)
320 this.timeout_add();
321 else
322 this.timeout_remove();
323 }else{
324 this.m_Model.aabb = true;
325 this.timeout_add();
329 public void init_anim()
331 this.m_View.reset();
332 this.m_Model.reset_anim();
334 this.invalidate();
337 Gtk.Menu create_popup_menu()
339 Gtk.Menu menu = new Gtk.Menu();
341 //Gtk.Menu.MenuList menu_list = menu.items();
343 // Enable/Disable Bullet Draw
345 menu_list.push_back(
346 Gtk::Menu_Helpers::MenuElem("Enable/Disable Bullet Draw",
347 sigc::mem_fun(*this, &Scene::bulletDraw)));
348 // Wireframe
349 menu_list.push_back(
350 Gtk::Menu_Helpers::MenuElem("Wireframe",
351 sigc::mem_fun(*this, &Scene::wireframe_view)));
352 // Ortho view
353 menu_list.push_back(
354 Gtk::Menu_Helpers::MenuElem("Enable/Disable Ortho View",
355 sigc::mem_fun(*this, &Scene::orthoView)));
356 // AAbbBox
357 menu_list.push_back(
358 Gtk::Menu_Helpers::MenuElem("Render AABB box",
359 sigc::mem_fun(*this, &Scene::AAbbBoxDraw)));
360 // Init orientation
361 menu_list.push_back(
362 Gtk::Menu_Helpers::MenuElem("Initialize",
363 sigc::mem_fun(*this, &Scene::init_anim)));
365 // Quit
366 menu_list.push_back(
367 Gtk::Menu_Helpers::MenuElem("Quit",
368 sigc::ptr_fun(&Gtk::Main::quit)));
370 return menu;
373 } // namespace Hkl3dGui