1 module nanogui.glcanvas; 2 /* 3 NanoGUI was developed by Wenzel Jakob <wenzel.jakob@epfl.ch>. 4 The widget drawing code is based on the NanoVG demo application 5 by Mikko Mononen. 6 7 All rights reserved. Use of this source code is governed by a 8 BSD-style license that can be found in the LICENSE.txt file. 9 */ 10 /** 11 * \file nanogui/glcanvas.h 12 * 13 * \brief Canvas widget for rendering OpenGL content. This widget was 14 * contributed by Jan Winkler. 15 */ 16 17 import nanogui.widget; 18 // #include <nanogui/opengl.h> 19 // #include <nanogui/glutil.h> 20 21 /** 22 * \class GLCanvas glcanvas.d 23 * 24 * \brief Canvas widget for rendering OpenGL content. This widget was 25 * contributed by Jan Winkler. 26 * 27 * Canvas widget that can be used to display arbitrary OpenGL content. This is 28 * useful to display and manipulate 3D objects as part of an interactive 29 * application. The implementation uses scissoring to ensure that rendered 30 * objects don't spill into neighboring widgets. 31 * 32 * \rst 33 * **Usage** 34 * Override :func:`nanogui.GLCanvas.drawGL` in subclasses to provide 35 * custom drawing code. 36 * 37 * \endrst 38 */ 39 class GLCanvas : Widget 40 { 41 import nanogui.common : Vector2f, Vector2i, Vector4i; 42 public: 43 /** 44 * Creates a GLCanvas attached to the specified parent. 45 * 46 * \param parent 47 * The Widget to attach this GLCanvas to. 48 */ 49 this(Widget parent) 50 { 51 super(parent); 52 mBackgroundColor = Vector4i(128, 128, 128, 255); 53 mDrawBorder = true; 54 mSize = Vector2i(250, 250); 55 } 56 57 /// Returns the background color. 58 final const(Color) backgroundColor() const { return mBackgroundColor; } 59 60 /// Sets the background color. 61 final void backgroundColor(const Color backgroundColor) { mBackgroundColor = backgroundColor; } 62 63 /// Set whether to draw the widget border or not. 64 final void drawBorder(const bool bDrawBorder) { mDrawBorder = bDrawBorder; } 65 66 /// Return whether the widget border gets drawn or not. 67 bool drawBorder() const { return mDrawBorder; } 68 69 /// Draw the canvas. 70 override void draw(ref NanoContext ctx) 71 { 72 Widget.draw(ctx); 73 74 if (mDrawBorder) 75 drawWidgetBorder(ctx); 76 77 ctx.endFrame; 78 79 const screen = this.screen(); 80 assert(screen); 81 82 float pixelRatio = screen.pixelRatio; 83 auto screenSize = cast(Vector2f) screen.size; 84 Vector2i positionInScreen = absolutePosition; 85 86 auto size = cast(Vector2i)(cast(Vector2f)mSize * pixelRatio); 87 auto imagePosition = cast(Vector2i)(Vector2f(positionInScreen[0], 88 screenSize[1] - positionInScreen[1] - 89 cast(float) mSize[1]) * pixelRatio); 90 91 import gfm.opengl; 92 GLint[4] storedViewport; 93 glGetIntegerv(GL_VIEWPORT, storedViewport.ptr); 94 95 glViewport(imagePosition[0], imagePosition[1], size[0] , size[1]); 96 97 glEnable(GL_SCISSOR_TEST); 98 glScissor(imagePosition[0], imagePosition[1], size[0], size[1]); 99 glClearColor(mBackgroundColor[0], mBackgroundColor[1], 100 mBackgroundColor[2], mBackgroundColor[3]); 101 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 102 103 this.drawGL(); 104 105 glDisable(GL_SCISSOR_TEST); 106 glViewport(storedViewport[0], storedViewport[1], 107 storedViewport[2], storedViewport[3]); 108 109 ctx.beginFrame(screen.size.x, screen.size.y); 110 } 111 112 /// Draw the GL scene. Override this method to draw the actual GL content. 113 void drawGL() {} 114 115 // /// Save the state of this GLCanvas to the specified Serializer. 116 // virtual void save(Serializer &s) const override; 117 118 // /// Set the state of this GLCanvas from the specified Serializer. 119 // virtual bool load(Serializer &s) override; 120 121 protected: 122 /// Internal helper function for drawing the widget border 123 void drawWidgetBorder(NanoContext ctx) const 124 { 125 // import arsd.nanovega; 126 ctx.beginPath; 127 ctx.strokeWidth(1.0f); 128 ctx.roundedRect(mPos.x - 0.5f, mPos.y - 0.5f, 129 mSize.x + 1, mSize.y + 1, mTheme.mWindowCornerRadius); 130 ctx.strokeColor(mTheme.mBorderLight); 131 ctx.roundedRect(mPos.x - 1.0f, mPos.y - 1.0f, 132 mSize.x + 2, mSize.y + 2, mTheme.mWindowCornerRadius); 133 ctx.strokeColor(mTheme.mBorderDark); 134 ctx.stroke; 135 } 136 137 protected: 138 /// The background color (what is used with ``glClearColor``). 139 Color mBackgroundColor; 140 141 /// Whether to draw the widget border or not. 142 bool mDrawBorder; 143 144 }