85
|
1 module doodle.gtk.opengl_canvas;
|
|
2
|
|
3 public {
|
|
4 import doodle.dia.icanvas;
|
|
5 import doodle.gtk.events;
|
|
6 }
|
|
7
|
|
8 private {
|
|
9 import doodle.core.logging;
|
|
10 import doodle.tk.screen_model;
|
|
11 import doodle.dia.layer_stack;
|
|
12 import doodle.gtk.cairo_renderer;
|
|
13
|
|
14 import cairo.Surface;
|
|
15 import cairo.Context;
|
|
16
|
|
17 import gtk.Widget;
|
|
18 import gtk.Toolbar;
|
|
19 import gtk.Table;
|
|
20 import gtk.HRuler;
|
|
21 import gtk.VRuler;
|
|
22 import gtk.Range;
|
|
23 import gtk.HScrollbar;
|
|
24 import gtk.VScrollbar;
|
|
25 import gtk.DrawingArea;
|
|
26 import gtk.Adjustment;
|
|
27
|
|
28 import gdk.Drawable;
|
|
29
|
|
30 import gtkc.gtk;
|
|
31 import gtkc.gtktypes;
|
|
32 //import gtkc.gdktypes;
|
|
33
|
|
34 import std.math;
|
|
35 import std.stdio;
|
|
36 }
|
|
37
|
|
38 final class OpenGLCanvas : Table, private IViewport {
|
|
39 this(in Layer[] layers, IEventHandler eventHandler, IGrid grid, in double pixelsPerMillimetre) {
|
|
40 super(3, 3, 0);
|
|
41
|
|
42 _damageScreen = Rectangle.DEFAULT;
|
|
43
|
|
44 _eventHandler = eventHandler;
|
|
45 _grid = grid;
|
|
46 _pixelsPerMillimetre = pixelsPerMillimetre;
|
|
47
|
|
48 _layerStack = new LayerStack(layers);
|
|
49
|
|
50 // Create our child widgets and register callbacks
|
|
51
|
|
52 _hRuler = new HRuler;
|
|
53 attach(_hRuler,
|
|
54 1, 2,
|
|
55 0, 1,
|
|
56 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK,
|
|
57 0, 0);
|
|
58 _hRuler.setMetric(MetricType.PIXELS);
|
|
59
|
|
60 _vRuler = new VRuler;
|
|
61 attach(_vRuler,
|
|
62 0, 1,
|
|
63 1, 2,
|
|
64 AttachOptions.SHRINK, AttachOptions.FILL | AttachOptions.EXPAND,
|
|
65 0, 0);
|
|
66 _vRuler.setMetric(MetricType.PIXELS);
|
|
67
|
|
68 _drawingArea = new GLDrawingArea;
|
|
69 _drawingArea.addOnRealize(&onRealize);
|
|
70 _drawingArea.addOnConfigure(&onConfigure);
|
|
71 _drawingArea.addOnExpose(&onExpose);
|
|
72 _drawingArea.addOnButtonPress(&onButtonPress);
|
|
73 _drawingArea.addOnButtonRelease(&onButtonRelease);
|
|
74 _drawingArea.addOnKeyPress(&onKeyPressEvent);
|
|
75 _drawingArea.addOnKeyRelease(&onKeyReleaseEvent);
|
|
76 _drawingArea.addOnMotionNotify(&onMotionNotify);
|
|
77 _drawingArea.addOnScroll(&onScroll);
|
|
78 _drawingArea.addOnEnterNotify(&onEnterNotify);
|
|
79 _drawingArea.addOnLeaveNotify(&onLeaveNotify);
|
|
80
|
|
81 _drawingArea.addOnFocusIn(&onFocusIn);
|
|
82 _drawingArea.addOnFocusOut(&onFocusOut);
|
|
83 _drawingArea.addOnMoveFocus(&onMoveFocus);
|
|
84 _drawingArea.addOnGrabBroken(&onGrabBroken);
|
|
85 _drawingArea.addOnGrabFocus(&onGrabFocus);
|
|
86 _drawingArea.addOnGrabNotify(&onGrabNotify);
|
|
87 // addOnPopupMenu
|
|
88 // addOnQueryTooltip
|
|
89 // addOnSelection*
|
|
90 _drawingArea.setEvents(EventMask.EXPOSURE_MASK |
|
|
91 EventMask.POINTER_MOTION_MASK |
|
|
92 EventMask.POINTER_MOTION_HINT_MASK |
|
|
93 EventMask.BUTTON_MOTION_MASK |
|
|
94 EventMask.BUTTON_PRESS_MASK |
|
|
95 EventMask.BUTTON_RELEASE_MASK |
|
|
96 EventMask.KEY_PRESS_MASK |
|
|
97 EventMask.KEY_RELEASE_MASK |
|
|
98 EventMask.ENTER_NOTIFY_MASK |
|
|
99 EventMask.LEAVE_NOTIFY_MASK |
|
|
100 EventMask.FOCUS_CHANGE_MASK |
|
|
101 EventMask.SCROLL_MASK);
|
|
102
|
|
103 _drawingArea.setCanFocus(true);
|
|
104
|
|
105 attach(_drawingArea,
|
|
106 1, 2,
|
|
107 1, 2,
|
|
108 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL | AttachOptions.EXPAND,
|
|
109 0, 0);
|
|
110
|
|
111 // value, lower, upper, step-inc, page-inc, page-size
|
|
112 // Give the adjustments dummy values until we receive a configure
|
|
113 _hAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.5);
|
|
114 _hAdjustment.addOnValueChanged(&onAdjustmentValueChanged);
|
|
115 _hScrollbar = new HScrollbar(_hAdjustment);
|
|
116 _hScrollbar.setInverted(false);
|
|
117 attach(_hScrollbar,
|
|
118 1, 2,
|
|
119 2, 3,
|
|
120 AttachOptions.FILL | AttachOptions.EXPAND,
|
|
121 AttachOptions.SHRINK,
|
|
122 0, 0);
|
|
123
|
|
124 _vAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.5);
|
|
125 _vAdjustment.addOnValueChanged(&onAdjustmentValueChanged);
|
|
126 _vScrollbar = new VScrollbar(_vAdjustment);
|
|
127 _vScrollbar.setInverted(true);
|
|
128 attach(_vScrollbar,
|
|
129 2, 3,
|
|
130 1, 2,
|
|
131 AttachOptions.SHRINK,
|
|
132 AttachOptions.FILL | AttachOptions.EXPAND,
|
|
133 0, 0);
|
|
134
|
|
135 _cursors = [
|
|
136 Cursor.DEFAULT : CursorType.ARROW,
|
|
137 Cursor.HAND : CursorType.HAND1,
|
|
138 Cursor.CROSSHAIR : CursorType.CROSSHAIR,
|
|
139 Cursor.PENCIL : CursorType.PENCIL
|
|
140 ];
|
|
141 }
|
|
142
|
|
143 protected { // XXX the compiler complains about unimplemented methods if this is private
|
|
144
|
|
145 // IViewport overrides:
|
|
146
|
|
147 void zoomRelative(in Point screenDatum, in double factor) {
|
|
148 _screenModel.zoomRelative(factor, screenDatum);
|
|
149 consolidateBounds;
|
|
150 updateAdjustments;
|
|
151 updateRulers;
|
|
152 _grid.zoomChanged(_screenModel.zoom);
|
|
153 queueDraw;
|
|
154 }
|
|
155
|
|
156 void panRelative(in Vector screenDisplacement) {
|
|
157 _screenModel.panRelativeScreen(screenDisplacement);
|
|
158 consolidateBounds;
|
|
159 updateAdjustments;
|
|
160 updateRulers;
|
|
161 queueDraw;
|
|
162 }
|
|
163
|
|
164 void setCursor(in Cursor cursor) {
|
|
165 _drawingArea.setCursor(new gdk.Cursor.Cursor(_cursors[cursor]));
|
|
166 }
|
|
167
|
|
168 void damageModel(in Rectangle area) {
|
|
169 _damageScreen = _damageScreen | _screenModel.modelToScreen(area);
|
|
170 }
|
|
171
|
|
172 void damageScreen(in Rectangle area) {
|
|
173 _damageScreen = _damageScreen | area;
|
|
174 }
|
|
175 }
|
|
176
|
|
177 private {
|
|
178
|
|
179 void initialiseBounds(in Rectangle viewBoundsScreen) {
|
|
180 Rectangle layerBounds = _layerStack.bounds;
|
|
181 Rectangle paddedLayerBounds = growCentre(layerBounds, 2 * layerBounds.size);
|
|
182 _screenModel = new ScreenModel(0.25 * _pixelsPerMillimetre, paddedLayerBounds, viewBoundsScreen);
|
|
183 _grid.zoomChanged(_screenModel.zoom);
|
|
184
|
|
185 updateAdjustments;
|
|
186 updateRulers;
|
|
187 }
|
|
188
|
|
189 void consolidateBounds() {
|
|
190 Rectangle layerBounds = _layerStack.bounds;
|
|
191 Rectangle paddedLayerBounds = growCentre(layerBounds, 2 * layerBounds.size);
|
|
192 _screenModel.consolidateCanvasBounds(paddedLayerBounds);
|
|
193
|
|
194 updateAdjustments;
|
|
195 updateRulers;
|
|
196 }
|
|
197
|
|
198 bool onConfigure(GdkEventConfigure * event, Widget widget) {
|
|
199 assert(widget is _drawingArea);
|
|
200 assert(event);
|
|
201
|
|
202 trace("onConfigure %sx%s", event.width, event.height);
|
|
203
|
|
204 Rectangle viewBoundsScreen = Rectangle(Point(0.0, 0.0), Vector(cast(double)event.width, cast(double)event.height));
|
|
205 if (_screenModel is null) { initialiseBounds(viewBoundsScreen); }
|
|
206 else { consolidateBounds; }
|
|
207
|
|
208 return true;
|
|
209 }
|
|
210
|
|
211 bool onExpose(GdkEventExpose * event, Widget widget) {
|
|
212 assert(widget is _drawingArea);
|
|
213 assert(event);
|
|
214
|
|
215 trace("onExpose %sx%s", event.area.width, event.area.height);
|
|
216
|
|
217 /+
|
|
218 Drawable dr = _drawingArea.getWindow;
|
|
219
|
|
220 int width, height;
|
|
221 dr.getSize(width, height);
|
|
222 //trace("Got expose %dx%d\n", width, height);
|
|
223
|
|
224 scope modelCr = new Context(dr);
|
|
225 scope screenCr = new Context(dr);
|
|
226
|
|
227 Rectangle screenDamage =
|
|
228 event is null ? _screenModel.viewBoundsScreen :
|
|
229 Rectangle(_screenModel.viewBoundsScreen.position + Vector(cast(double)event.area.x, _screenModel.viewBoundsScreen.h - cast(double)(event.area.y + event.area.height)),
|
|
230 Vector(cast(double)event.area.width, cast(double)event.area.height));
|
|
231
|
|
232 Rectangle modelDamage = _screenModel.screenToModel(screenDamage);
|
|
233
|
|
234 modelCr.save; screenCr.save; {
|
|
235 {
|
|
236 // Setup model context and clip
|
|
237 modelCr.translate(0.0, _screenModel.viewBoundsScreen.h);
|
|
238 modelCr.scale(_screenModel.zoom, -_screenModel.zoom);
|
|
239
|
|
240 immutable Point viewLeftBottom = _screenModel.screenToModel(Point(0.0, 0.0));
|
|
241 modelCr.translate(-viewLeftBottom.x, -viewLeftBottom.y);
|
|
242
|
|
243 modelCr.rectangle(modelDamage.x0, modelDamage.y0, modelDamage.w, modelDamage.h);
|
|
244 modelCr.clip;
|
|
245 }
|
|
246
|
|
247 {
|
|
248 // Setup screen context and clip
|
|
249 screenCr.translate(0.0, _screenModel.viewBoundsScreen.h);
|
|
250 screenCr.scale(1.0, -1.0);
|
|
251
|
|
252 screenCr.rectangle(screenDamage.x0, screenDamage.y0, screenDamage.w, screenDamage.h);
|
|
253 screenCr.clip;
|
|
254 }
|
|
255
|
|
256 screenCr.save; {
|
|
257 // Fill the background with light grey
|
|
258 screenCr.setSourceRgba(0.9, 0.9, 0.9, 1.0);
|
|
259 screenCr.rectangle(screenDamage.x0, screenDamage.y0, screenDamage.w, screenDamage.h);
|
|
260 screenCr.fill;
|
|
261 } screenCr.restore;
|
|
262
|
|
263 _layerStack.draw(screenDamage, new CairoRenderer(screenCr),
|
|
264 modelDamage, new CairoRenderer(modelCr));
|
|
265 } screenCr.restore; modelCr.restore;
|
|
266
|
|
267 return true;
|
|
268 +/
|
|
269
|
|
270 return false;
|
|
271 }
|
|
272
|
|
273 bool onButtonPress(GdkEventButton * event, Widget widget) {
|
|
274 assert(widget is _drawingArea);
|
|
275 _eventHandler.handleButtonPress(this, makeButtonEvent(event, _screenModel));
|
|
276 fixDamage;
|
|
277 return true;
|
|
278 }
|
|
279
|
|
280 bool onButtonRelease(GdkEventButton * event, Widget widget) {
|
|
281 assert(widget is _drawingArea);
|
|
282 _eventHandler.handleButtonRelease(this, makeButtonEvent(event, _screenModel));
|
|
283 fixDamage;
|
|
284 return true;
|
|
285 }
|
|
286
|
|
287 bool onKeyPressEvent(GdkEventKey * event, Widget widget) {
|
|
288 assert(widget is _drawingArea);
|
|
289 _eventHandler.handleKeyPress(this, makeKeyEvent(event, _screenModel));
|
|
290 fixDamage;
|
|
291 return true;
|
|
292 }
|
|
293
|
|
294 bool onKeyReleaseEvent(GdkEventKey * event, Widget widget) {
|
|
295 assert(widget is _drawingArea);
|
|
296 _eventHandler.handleKeyRelease(this, makeKeyEvent(event, _screenModel));
|
|
297 fixDamage;
|
|
298 return true;
|
|
299 }
|
|
300
|
|
301 bool onMotionNotify(GdkEventMotion * event, Widget widget) {
|
|
302 assert(widget is _drawingArea);
|
|
303
|
|
304 // Pass the events on to the rulers so that they update
|
|
305 gtk_widget_event(_hRuler.getWidgetStruct(), cast(GdkEvent *)event);
|
|
306 gtk_widget_event(_vRuler.getWidgetStruct(), cast(GdkEvent *)event);
|
|
307
|
|
308 _eventHandler.handleMotion(this, makeMotionEvent(event, _screenModel));
|
|
309 fixDamage;
|
|
310 return true;
|
|
311 }
|
|
312
|
|
313 bool onScroll(GdkEventScroll * event, Widget widget) {
|
|
314 assert(widget is _drawingArea);
|
|
315 _eventHandler.handleScroll(this, makeScrollEvent(event, _screenModel));
|
|
316 fixDamage;
|
|
317 return true;
|
|
318 }
|
|
319
|
|
320 bool onEnterNotify(GdkEventCrossing * event, Widget widget) {
|
|
321 trace("1");
|
|
322 assert(widget is _drawingArea);
|
|
323 trace("2");
|
|
324 _eventHandler.handleEnter(this, makeCrossingEvent(event, _screenModel));
|
|
325 trace("3");
|
|
326 fixDamage;
|
|
327 trace("4");
|
|
328 return true;
|
|
329 }
|
|
330
|
|
331 bool onLeaveNotify(GdkEventCrossing * event, Widget widget) {
|
|
332 assert(widget is _drawingArea);
|
|
333 _eventHandler.handleLeave(this, makeCrossingEvent(event, _screenModel));
|
|
334 fixDamage;
|
|
335 return true;
|
|
336 }
|
|
337
|
|
338 bool onFocusIn(GdkEventFocus * event, Widget widget) {
|
|
339 trace("onFocusIn");
|
|
340 return true;
|
|
341 }
|
|
342
|
|
343 bool onFocusOut(GdkEventFocus * event, Widget widget) {
|
|
344 trace("onFocusOut");
|
|
345 return true;
|
|
346 }
|
|
347
|
|
348 void onMoveFocus(GtkDirectionType direction, Widget widget) {
|
|
349 trace("onMoveFocus");
|
|
350 }
|
|
351
|
|
352 bool onGrabBroken(gdk.Event.Event event, Widget widget) {
|
|
353 trace("onGrabBroken");
|
|
354 return true;
|
|
355 }
|
|
356
|
|
357 void onGrabFocus(Widget widget) {
|
|
358 //trace("onGrabFocus");
|
|
359 }
|
|
360
|
|
361 void onGrabNotify(gboolean what, Widget widget){
|
|
362 trace("onGrabNotify");
|
|
363 }
|
|
364
|
|
365 void onAdjustmentValueChanged(Adjustment adjustment) {
|
|
366 GtkAdjustment * hGtkAdjustment = _hAdjustment.getAdjustmentStruct;
|
|
367 GtkAdjustment * vGtkAdjustment = _vAdjustment.getAdjustmentStruct;
|
|
368
|
|
369 Point oldViewLeftBottom = _screenModel.screenToModel(Point(0.0, 0.0));
|
|
370 Point newViewLeftBottom = Point(gtk_adjustment_get_value(hGtkAdjustment),
|
|
371 gtk_adjustment_get_value(vGtkAdjustment));
|
|
372
|
|
373 _screenModel.panRelativeModel(newViewLeftBottom - oldViewLeftBottom);
|
|
374
|
|
375 updateRulers;
|
|
376 queueDraw;
|
|
377 }
|
|
378
|
|
379 void updateRulers() {
|
|
380 immutable Point viewLeftBottom = _screenModel.screenToModel(_screenModel.viewBoundsScreen.corner0);
|
|
381 immutable Point viewRightTop = _screenModel.screenToModel(_screenModel.viewBoundsScreen.corner1);
|
|
382
|
|
383 // Define these just to obtain the position
|
|
384 // below so we can preserve it
|
|
385 double lower, upper, position, maxSize;
|
|
386
|
|
387 _hRuler.getRange(lower, upper, position, maxSize);
|
|
388 _hRuler.setRange(viewLeftBottom.x,
|
|
389 viewRightTop.x,
|
|
390 position,
|
|
391 _screenModel.zoom * 50.0);
|
|
392
|
|
393 _vRuler.getRange(lower, upper, position, maxSize);
|
|
394 _vRuler.setRange(viewRightTop.y,
|
|
395 viewLeftBottom.y,
|
|
396 position,
|
|
397 _screenModel.zoom * 50.0);
|
|
398 }
|
|
399
|
|
400 void updateAdjustments() {
|
|
401 immutable Point viewLeftBottom = _screenModel.screenToModel(Point(0.0, 0.0));
|
|
402 immutable Point viewRightTop = _screenModel.screenToModel(_screenModel.viewBoundsScreen.corner1);
|
|
403
|
|
404 // Adjust the canvas size if necessary
|
|
405 _screenModel.canvasAccommodate(Rectangle(viewLeftBottom, viewRightTop));
|
|
406
|
|
407 Rectangle viewBoundsModel = _screenModel.viewBoundsModel;
|
|
408
|
|
409 // Update the adjustments
|
|
410
|
|
411 GtkAdjustment * hGtkAdjustment = _hAdjustment.getAdjustmentStruct;
|
|
412 GtkAdjustment * vGtkAdjustment = _vAdjustment.getAdjustmentStruct;
|
|
413
|
|
414 gtk_adjustment_set_lower(hGtkAdjustment, _screenModel.canvasBoundsModel.x0);
|
|
415 gtk_adjustment_set_upper(hGtkAdjustment, _screenModel.canvasBoundsModel.x1);
|
|
416 gtk_adjustment_set_value(hGtkAdjustment, viewLeftBottom.x);
|
|
417 gtk_adjustment_set_step_increment(hGtkAdjustment, _screenModel.canvasBoundsModel.w / 16.0);
|
|
418 gtk_adjustment_set_page_increment(hGtkAdjustment, _screenModel.canvasBoundsModel.w / 4.0);
|
|
419 gtk_adjustment_set_page_size(hGtkAdjustment, viewBoundsModel.w);
|
|
420
|
|
421 gtk_adjustment_set_lower(vGtkAdjustment, _screenModel.canvasBoundsModel.y0);
|
|
422 gtk_adjustment_set_upper(vGtkAdjustment, _screenModel.canvasBoundsModel.y1);
|
|
423 gtk_adjustment_set_value(vGtkAdjustment, viewLeftBottom.y);
|
|
424 gtk_adjustment_set_step_increment(vGtkAdjustment, _screenModel.canvasBoundsModel.h / 16.0);
|
|
425 gtk_adjustment_set_page_increment(vGtkAdjustment, _screenModel.canvasBoundsModel.h / 4.0);
|
|
426 gtk_adjustment_set_page_size(vGtkAdjustment, viewBoundsModel.h);
|
|
427
|
|
428 _hAdjustment.changed;
|
|
429 _hAdjustment.valueChanged;
|
|
430 _vAdjustment.changed;
|
|
431 _vAdjustment.valueChanged;
|
|
432 }
|
|
433
|
|
434 void fixDamage() {
|
|
435 if (_damageScreen.valid) {
|
|
436 int x, y, w, h;
|
|
437 _damageScreen.getQuantised(x, y, w, h);
|
|
438 _drawingArea.queueDrawArea(x, cast(int)_screenModel.viewBoundsScreen.h - (y + h), w, h);
|
|
439 _damageScreen = Rectangle.DEFAULT;
|
|
440 }
|
|
441 }
|
|
442
|
|
443 void onRealize(Widget widget) {
|
|
444 assert(widget is _drawingArea);
|
|
445 _drawingArea.grabFocus();
|
|
446 }
|
|
447
|
|
448 IEventHandler _eventHandler;
|
|
449 IGrid _grid;
|
|
450 double _pixelsPerMillimetre;
|
|
451 LayerStack _layerStack;
|
|
452
|
|
453 // Child widgets:
|
|
454 HRuler _hRuler;
|
|
455 VRuler _vRuler;
|
|
456 DrawingArea _drawingArea;
|
|
457 Adjustment _hAdjustment;
|
|
458 HScrollbar _hScrollbar;
|
|
459 Adjustment _vAdjustment;
|
|
460 VScrollbar _vScrollbar;
|
|
461
|
|
462 Rectangle _damageScreen;
|
|
463 ScreenModel _screenModel;
|
|
464
|
|
465 immutable CursorType[Cursor] _cursors;
|
|
466 }
|
|
467 }
|
|
468
|
|
469 private import gtk.DrawingArea;
|
|
470 private import glgtk.GLCapability;
|
|
471 private import glgdk.GLDrawable;
|
|
472 private import glgdk.GLConfig;
|
|
473 private import glgdk.GLContext;
|
|
474 private import gtkglc.glgdktypes;
|
|
475
|
|
476 private import gtkglc.gl;
|
|
477 private import gtkglc.glu;
|
|
478
|
|
479 private import gdk.Event;
|
|
480
|
|
481 private import gtk.Widget;
|
|
482
|
|
483 private import gtk.Main;
|
|
484 private import gtk.MainWindow;
|
|
485
|
|
486 class GLDrawingArea : DrawingArea {
|
|
487 GLfloat width;
|
|
488 GLfloat height;
|
|
489
|
|
490 /** need to include the mixin to add GL capabilities to this widget */
|
|
491 mixin GLCapability;
|
|
492
|
|
493 /**
|
|
494 * Construct a simple DrawingArea and sets the GLCapabilities
|
|
495 */
|
|
496 this() {
|
|
497 setGLCapability(); // set the GL capabilities for this widget
|
|
498 }
|
|
499
|
|
500 /**
|
|
501 * put any gl initializations here
|
|
502 * returns true to consume the event
|
|
503 */
|
|
504 bool initGL() {
|
|
505 trace("initGL");
|
|
506
|
|
507 resizeGL(null);
|
|
508 return true;
|
|
509 }
|
|
510
|
|
511 /**
|
|
512 * This method is called every time the window must be paint or repaint
|
|
513 * This is where you put the OpenGL call to draw something.
|
|
514 * This method call be called directly by the application without an event object
|
|
515 * to force redrawing of the scene.
|
|
516 * returns true to consume the event
|
|
517 */
|
|
518 bool drawGL(GdkEventExpose* event = null) {
|
|
519 trace("drawGL");
|
|
520
|
|
521 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
522 glLoadIdentity ();
|
|
523
|
|
524 gluLookAt(0, 0, 10, 0, 0, 0, 0, 1,0); //Set the camera position
|
|
525
|
|
526 //Just Draw a tri-colored triangle
|
|
527 glBegin(GL_TRIANGLES);
|
|
528 glColor3f(1.0f,0.0f,0.0f);
|
|
529 glVertex3f( 0.0f, 1.0f, 0.0f);
|
|
530 glColor3f(0.0f,1.0f,0.0f);
|
|
531 glVertex3f(-1.0f,-1.0f, 0.0f);
|
|
532 glColor3f(0.0f,0.0f,1.0f);
|
|
533 glVertex3f( 1.0f,-1.0f, 0.0f);
|
|
534 glEnd();
|
|
535
|
|
536 return true;
|
|
537 }
|
|
538
|
|
539 /**
|
|
540 * This method is called when the window is resized
|
|
541 * returns true to consume the event
|
|
542 */
|
|
543 bool resizeGL(GdkEventConfigure* event = null) {
|
|
544 trace("resizeGL");
|
|
545
|
|
546 if (event == null) {
|
|
547 width = getWidth();
|
|
548 height = getHeight();
|
|
549 }
|
|
550 else {
|
|
551 width = event.width;
|
|
552 height = event.height;
|
|
553 }
|
|
554
|
|
555 trace("Size %sx%s", width, height);
|
|
556
|
|
557 glViewport(0, 0, cast(int)width, cast(int)height); //Adjust the viewport according to new window dimensions
|
|
558
|
|
559 /*
|
|
560 * Update the projection Matrix accoding to the new dimension
|
|
561 * and reset the OpenGL state to MODELVIEW
|
|
562 */
|
|
563 glMatrixMode(GL_PROJECTION);
|
|
564 glLoadIdentity();
|
|
565 gluPerspective(20, width/height, 0.1, 10);
|
|
566 glMatrixMode(GL_MODELVIEW);
|
|
567
|
|
568 return false;
|
|
569 }
|
|
570 }
|