1 | /* |
2 | nanogui/glcanvas.cpp -- Canvas widget for rendering full-fledged |
3 | OpenGL content within its designated area. Very useful for |
4 | displaying and manipulating 3D objects or scenes. Subclass it and |
5 | overload `drawGL` for rendering. |
6 | |
7 | NanoGUI was developed by Wenzel Jakob <wenzel.jakob@epfl.ch>. |
8 | The widget drawing code is based on the NanoVG demo application |
9 | by Mikko Mononen. |
10 | |
11 | All rights reserved. Use of this source code is governed by a |
12 | BSD-style license that can be found in the LICENSE.txt file. |
13 | */ |
14 | |
15 | #include <nanogui/window.h> |
16 | #include <nanogui/screen.h> |
17 | #include <nanogui/glcanvas.h> |
18 | #include <nanogui/theme.h> |
19 | #include <nanogui/opengl.h> |
20 | #include <nanogui/serializer/core.h> |
21 | |
22 | NAMESPACE_BEGIN(nanogui) |
23 | |
24 | GLCanvas::GLCanvas(Widget *parent) |
25 | : Widget(parent), mBackgroundColor(Vector4i(128, 128, 128, 255)), |
26 | mDrawBorder(true) { |
27 | mSize = Vector2i(250, 250); |
28 | } |
29 | |
30 | void GLCanvas::drawWidgetBorder(NVGcontext *ctx) const { |
31 | nvgBeginPath(ctx); |
32 | nvgStrokeWidth(ctx, 1.0f); |
33 | nvgRoundedRect(ctx, mPos.x() - 0.5f, mPos.y() - 0.5f, |
34 | mSize.x() + 1, mSize.y() + 1, mTheme->mWindowCornerRadius); |
35 | nvgStrokeColor(ctx, mTheme->mBorderLight); |
36 | nvgRoundedRect(ctx, mPos.x() - 1.0f, mPos.y() - 1.0f, |
37 | mSize.x() + 2, mSize.y() + 2, mTheme->mWindowCornerRadius); |
38 | nvgStrokeColor(ctx, mTheme->mBorderDark); |
39 | nvgStroke(ctx); |
40 | } |
41 | |
42 | void GLCanvas::draw(NVGcontext *ctx) { |
43 | Widget::draw(ctx); |
44 | nvgEndFrame(ctx); |
45 | |
46 | if (mDrawBorder) |
47 | drawWidgetBorder(ctx); |
48 | |
49 | const Screen* screen = this->screen(); |
50 | assert(screen); |
51 | |
52 | float pixelRatio = screen->pixelRatio(); |
53 | Vector2f screenSize = screen->size().cast<float>(); |
54 | Vector2i positionInScreen = absolutePosition(); |
55 | |
56 | Vector2i size = (mSize.cast<float>() * pixelRatio).cast<int>(), |
57 | imagePosition = (Vector2f(positionInScreen[0], |
58 | screenSize[1] - positionInScreen[1] - |
59 | (float) mSize[1]) * pixelRatio).cast<int>(); |
60 | |
61 | GLint storedViewport[4]; |
62 | glGetIntegerv(GL_VIEWPORT, storedViewport); |
63 | |
64 | glViewport(imagePosition[0], imagePosition[1], size[0] , size[1]); |
65 | |
66 | glEnable(GL_SCISSOR_TEST); |
67 | glScissor(imagePosition[0], imagePosition[1], size[0], size[1]); |
68 | glClearColor(mBackgroundColor[0], mBackgroundColor[1], |
69 | mBackgroundColor[2], mBackgroundColor[3]); |
70 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
71 | |
72 | this->drawGL(); |
73 | |
74 | glDisable(GL_SCISSOR_TEST); |
75 | glViewport(storedViewport[0], storedViewport[1], |
76 | storedViewport[2], storedViewport[3]); |
77 | } |
78 | |
79 | void GLCanvas::save(Serializer &s) const { |
80 | Widget::save(s); |
81 | s.set("backgroundColor" , mBackgroundColor); |
82 | s.set("drawBorder" , mDrawBorder); |
83 | } |
84 | |
85 | bool GLCanvas::load(Serializer &s) { |
86 | if (!Widget::load(s)) return false; |
87 | if (!s.get("backgroundColor" , mBackgroundColor)) return false; |
88 | if (!s.get("drawBorder" , mDrawBorder)) return false; |
89 | return true; |
90 | } |
91 | |
92 | NAMESPACE_END(nanogui) |
93 | |