1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gtk.GLArea; 26 27 private import gdk.GLContext; 28 private import glib.ConstructionException; 29 private import glib.ErrorG; 30 private import gobject.ObjectG; 31 private import gobject.Signals; 32 private import gtk.Widget; 33 public import gtkc.gdktypes; 34 private import gtkc.gtk; 35 public import gtkc.gtktypes; 36 37 38 /** 39 * #GtkGLArea is a widget that allows drawing with OpenGL. 40 * 41 * #GtkGLArea sets up its own #GdkGLContext for the window it creates, and 42 * creates a custom GL framebuffer that the widget will do GL rendering onto. 43 * It also ensures that this framebuffer is the default GL rendering target 44 * when rendering. 45 * 46 * In order to draw, you have to connect to the #GtkGLArea::render signal, 47 * or subclass #GtkGLArea and override the @GtkGLAreaClass.render() virtual 48 * function. 49 * 50 * The #GtkGLArea widget ensures that the #GdkGLContext is associated with 51 * the widget's drawing area, and it is kept updated when the size and 52 * position of the drawing area changes. 53 * 54 * ## Drawing with GtkGLArea ## 55 * 56 * The simplest way to draw using OpenGL commands in a #GtkGLArea is to 57 * create a widget instance and connect to the #GtkGLArea::render signal: 58 * 59 * |[<!-- language="C" --> 60 * // create a GtkGLArea instance 61 * GtkWidget *gl_area = gtk_gl_area_new (); 62 * 63 * // connect to the "render" signal 64 * g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL); 65 * ]| 66 * 67 * The `render()` function will be called when the #GtkGLArea is ready 68 * for you to draw its content: 69 * 70 * |[<!-- language="C" --> 71 * static gboolean 72 * render (GtkGLArea *area, GdkGLContext *context) 73 * { 74 * // inside this function it's safe to use GL; the given 75 * // #GdkGLContext has been made current to the drawable 76 * // surface used by the #GtkGLArea and the viewport has 77 * // already been set to be the size of the allocation 78 * 79 * // we can start by clearing the buffer 80 * glClearColor (0, 0, 0, 0); 81 * glClear (GL_COLOR_BUFFER_BIT); 82 * 83 * // draw your object 84 * draw_an_object (); 85 * 86 * // we completed our drawing; the draw commands will be 87 * // flushed at the end of the signal emission chain, and 88 * // the buffers will be drawn on the window 89 * return TRUE; 90 * } 91 * ]| 92 * 93 * If you need to initialize OpenGL state, e.g. buffer objects or 94 * shaders, you should use the #GtkWidget::realize signal; you 95 * can use the #GtkWidget::unrealize signal to clean up. 96 * 97 * If you need to change the options for creating the #GdkGLContext 98 * you should use the #GtkGLArea::create-context signal. 99 * 100 * Since: 3.16 101 */ 102 public class GLArea : Widget 103 { 104 /** the main Gtk struct */ 105 protected GtkGLArea* gtkGLArea; 106 107 /** Get the main Gtk struct */ 108 public GtkGLArea* getGLAreaStruct() 109 { 110 return gtkGLArea; 111 } 112 113 /** the main Gtk struct as a void* */ 114 protected override void* getStruct() 115 { 116 return cast(void*)gtkGLArea; 117 } 118 119 protected override void setStruct(GObject* obj) 120 { 121 gtkGLArea = cast(GtkGLArea*)obj; 122 super.setStruct(obj); 123 } 124 125 /** 126 * Sets our main struct and passes it to the parent class. 127 */ 128 public this (GtkGLArea* gtkGLArea, bool ownedRef = false) 129 { 130 this.gtkGLArea = gtkGLArea; 131 super(cast(GtkWidget*)gtkGLArea, ownedRef); 132 } 133 134 /** 135 */ 136 137 public static GType getType() 138 { 139 return gtk_gl_area_get_type(); 140 } 141 142 /** 143 * Creates a new #GtkGLArea widget. 144 * 145 * Return: the newly created #GtkGLArea 146 * 147 * Since: 3.16 148 * 149 * Throws: ConstructionException GTK+ fails to create the object. 150 */ 151 public this() 152 { 153 auto p = gtk_gl_area_new(); 154 155 if(p is null) 156 { 157 throw new ConstructionException("null returned by new"); 158 } 159 160 this(cast(GtkGLArea*) p, true); 161 } 162 163 /** 164 * Ensures that the @area framebuffer object is made the current draw 165 * and read target, and that all the required buffers for the @area 166 * are created and bound to the frambuffer. 167 * 168 * This function is automatically called before emitting the 169 * #GtkGLArea::render signal, and doesn't normally need to be called 170 * by application code. 171 * 172 * Since: 3.16 173 */ 174 public void attachBuffers() 175 { 176 gtk_gl_area_attach_buffers(gtkGLArea); 177 } 178 179 /** 180 * Returns whether the area is in auto render mode or not. 181 * 182 * Return: %TRUE if the @area is auto rendering, %FALSE otherwise 183 * 184 * Since: 3.16 185 */ 186 public bool getAutoRender() 187 { 188 return gtk_gl_area_get_auto_render(gtkGLArea) != 0; 189 } 190 191 /** 192 * Retrieves the #GdkGLContext used by @area. 193 * 194 * Return: the #GdkGLContext 195 * 196 * Since: 3.16 197 */ 198 public GLContext getContext() 199 { 200 auto p = gtk_gl_area_get_context(gtkGLArea); 201 202 if(p is null) 203 { 204 return null; 205 } 206 207 return ObjectG.getDObject!(GLContext)(cast(GdkGLContext*) p); 208 } 209 210 /** 211 * Gets the current error set on the @area. 212 * 213 * Return: the #GError or %NULL 214 * 215 * Since: 3.16 216 */ 217 public ErrorG getError() 218 { 219 auto p = gtk_gl_area_get_error(gtkGLArea); 220 221 if(p is null) 222 { 223 return null; 224 } 225 226 return new ErrorG(cast(GError*) p); 227 } 228 229 /** 230 * Returns whether the area has an alpha component. 231 * 232 * Return: %TRUE if the @area has an alpha component, %FALSE otherwise 233 * 234 * Since: 3.16 235 */ 236 public bool getHasAlpha() 237 { 238 return gtk_gl_area_get_has_alpha(gtkGLArea) != 0; 239 } 240 241 /** 242 * Returns whether the area has a depth buffer. 243 * 244 * Return: %TRUE if the @area has a depth buffer, %FALSE otherwise 245 * 246 * Since: 3.16 247 */ 248 public bool getHasDepthBuffer() 249 { 250 return gtk_gl_area_get_has_depth_buffer(gtkGLArea) != 0; 251 } 252 253 /** 254 * Returns whether the area has a stencil buffer. 255 * 256 * Return: %TRUE if the @area has a stencil buffer, %FALSE otherwise 257 * 258 * Since: 3.16 259 */ 260 public bool getHasStencilBuffer() 261 { 262 return gtk_gl_area_get_has_stencil_buffer(gtkGLArea) != 0; 263 } 264 265 /** 266 * Retrieves the required version of OpenGL set 267 * using gtk_gl_area_set_required_version(). 268 * 269 * Params: 270 * major = return location for the required major version 271 * minor = return location for the required minor version 272 * 273 * Since: 3.16 274 */ 275 public void getRequiredVersion(out int major, out int minor) 276 { 277 gtk_gl_area_get_required_version(gtkGLArea, &major, &minor); 278 } 279 280 /** 281 * Ensures that the #GdkGLContext used by @area is associated with 282 * the #GtkGLArea. 283 * 284 * This function is automatically called before emitting the 285 * #GtkGLArea::render signal, and doesn't normally need to be called 286 * by application code. 287 * 288 * Since: 3.16 289 */ 290 public void makeCurrent() 291 { 292 gtk_gl_area_make_current(gtkGLArea); 293 } 294 295 /** 296 * Marks the currently rendered data (if any) as invalid, and queues 297 * a redraw of the widget, ensuring that the #GtkGLArea::render signal 298 * is emitted during the draw. 299 * 300 * This is only needed when the gtk_gl_area_set_auto_render() has 301 * been called with a %FALSE value. The default behaviour is to 302 * emit #GtkGLArea::render on each draw. 303 * 304 * Since: 3.16 305 */ 306 public void queueRender() 307 { 308 gtk_gl_area_queue_render(gtkGLArea); 309 } 310 311 /** 312 * If @auto_render is %TRUE the #GtkGLArea::render signal will be 313 * emitted every time the widget draws. This is the default and is 314 * useful if drawing the widget is faster. 315 * 316 * If @auto_render is %FALSE the data from previous rendering is kept 317 * around and will be used for drawing the widget the next time, 318 * unless the window is resized. In order to force a rendering 319 * gtk_gl_area_queue_render() must be called. This mode is useful when 320 * the scene changes seldomly, but takes a long time to redraw. 321 * 322 * Params: 323 * autoRender = a boolean 324 * 325 * Since: 3.16 326 */ 327 public void setAutoRender(bool autoRender) 328 { 329 gtk_gl_area_set_auto_render(gtkGLArea, autoRender); 330 } 331 332 /** 333 * Sets an error on the area which will be shown instead of the 334 * GL rendering. This is useful in the #GtkGLArea::create-context 335 * signal if GL context creation fails. 336 * 337 * Params: 338 * error = a new #GError, or %NULL to unset the error 339 * 340 * Since: 3.16 341 */ 342 public void setError(ErrorG error) 343 { 344 gtk_gl_area_set_error(gtkGLArea, (error is null) ? null : error.getErrorGStruct()); 345 } 346 347 /** 348 * If @has_alpha is %TRUE the buffer allocated by the widget will have 349 * an alpha channel component, and when rendering to the window the 350 * result will be composited over whatever is below the widget. 351 * 352 * If @has_alpha is %FALSE there will be no alpha channel, and the 353 * buffer will fully replace anything below the widget. 354 * 355 * Params: 356 * hasAlpha = %TRUE to add an alpha component 357 * 358 * Since: 3.16 359 */ 360 public void setHasAlpha(bool hasAlpha) 361 { 362 gtk_gl_area_set_has_alpha(gtkGLArea, hasAlpha); 363 } 364 365 /** 366 * If @has_depth_buffer is %TRUE the widget will allocate and 367 * enable a depth buffer for the target framebuffer. Otherwise 368 * there will be none. 369 * 370 * Params: 371 * hasDepthBuffer = %TRUE to add a depth buffer 372 * 373 * Since: 3.16 374 */ 375 public void setHasDepthBuffer(bool hasDepthBuffer) 376 { 377 gtk_gl_area_set_has_depth_buffer(gtkGLArea, hasDepthBuffer); 378 } 379 380 /** 381 * If @has_stencil_buffer is %TRUE the widget will allocate and 382 * enable a stencil buffer for the target framebuffer. Otherwise 383 * there will be none. 384 * 385 * Params: 386 * hasStencilBuffer = %TRUE to add a stencil buffer 387 * 388 * Since: 3.16 389 */ 390 public void setHasStencilBuffer(bool hasStencilBuffer) 391 { 392 gtk_gl_area_set_has_stencil_buffer(gtkGLArea, hasStencilBuffer); 393 } 394 395 /** 396 * Sets the required version of OpenGL to be used when creating the context 397 * for the widget. 398 * 399 * This function must be called before the area has been realized. 400 * 401 * Params: 402 * major = the major version 403 * minor = the minor version 404 * 405 * Since: 3.16 406 */ 407 public void setRequiredVersion(int major, int minor) 408 { 409 gtk_gl_area_set_required_version(gtkGLArea, major, minor); 410 } 411 412 int[string] connectedSignals; 413 414 GLContext delegate(GLArea)[] onCreateContextListeners; 415 /** 416 * The ::create-context signal is emitted when the widget is being 417 * realized, and allows you to override how the GL context is 418 * created. This is useful when you want to reuse an existing GL 419 * context, or if you want to try creating different kinds of GL 420 * options. 421 * 422 * If context creation fails then the signal handler can use 423 * gtk_gl_area_set_error() to register a more detailed error 424 * of how the construction failed. 425 * 426 * Return: a newly created #GdkGLContext; 427 * the #GtkGLArea widget will take ownership of the returned value. 428 * 429 * Since: 3.16 430 */ 431 void addOnCreateContext(GLContext delegate(GLArea) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 432 { 433 if ( "create-context" !in connectedSignals ) 434 { 435 Signals.connectData( 436 this, 437 "create-context", 438 cast(GCallback)&callBackCreateContext, 439 cast(void*)this, 440 null, 441 connectFlags); 442 connectedSignals["create-context"] = 1; 443 } 444 onCreateContextListeners ~= dlg; 445 } 446 extern(C) static GdkGLContext* callBackCreateContext(GtkGLArea* glareaStruct, GLArea _glarea) 447 { 448 foreach ( GLContext delegate(GLArea) dlg; _glarea.onCreateContextListeners ) 449 { 450 if ( auto r = dlg(_glarea) ) 451 return r.getGLContextStruct(); 452 } 453 454 return null; 455 } 456 457 bool delegate(GLContext, GLArea)[] onRenderListeners; 458 /** 459 * The ::render signal is emitted every time the contents 460 * of the #GtkGLArea should be redrawn. 461 * 462 * The @context is bound to the @area prior to emitting this function, 463 * and the buffers are painted to the window once the emission terminates. 464 * 465 * Params: 466 * context = the #GdkGLContext used by @area 467 * 468 * Return: %TRUE to stop other handlers from being invoked for the event. 469 * %FALSE to propagate the event further. 470 * 471 * Since: 3.16 472 */ 473 void addOnRender(bool delegate(GLContext, GLArea) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 474 { 475 if ( "render" !in connectedSignals ) 476 { 477 Signals.connectData( 478 this, 479 "render", 480 cast(GCallback)&callBackRender, 481 cast(void*)this, 482 null, 483 connectFlags); 484 connectedSignals["render"] = 1; 485 } 486 onRenderListeners ~= dlg; 487 } 488 extern(C) static int callBackRender(GtkGLArea* glareaStruct, GdkGLContext* context, GLArea _glarea) 489 { 490 foreach ( bool delegate(GLContext, GLArea) dlg; _glarea.onRenderListeners ) 491 { 492 if ( dlg(ObjectG.getDObject!(GLContext)(context), _glarea) ) 493 { 494 return 1; 495 } 496 } 497 498 return 0; 499 } 500 501 void delegate(int, int, GLArea)[] onResizeListeners; 502 void addOnResize(void delegate(int, int, GLArea) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 503 { 504 if ( "resize" !in connectedSignals ) 505 { 506 Signals.connectData( 507 this, 508 "resize", 509 cast(GCallback)&callBackResize, 510 cast(void*)this, 511 null, 512 connectFlags); 513 connectedSignals["resize"] = 1; 514 } 515 onResizeListeners ~= dlg; 516 } 517 extern(C) static void callBackResize(GtkGLArea* glareaStruct, int object, int p0, GLArea _glarea) 518 { 519 foreach ( void delegate(int, int, GLArea) dlg; _glarea.onResizeListeners ) 520 { 521 dlg(object, p0, _glarea); 522 } 523 } 524 }