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
22NAMESPACE_BEGIN(nanogui)
23
24GLCanvas::GLCanvas(Widget *parent)
25 : Widget(parent), mBackgroundColor(Vector4i(128, 128, 128, 255)),
26 mDrawBorder(true) {
27 mSize = Vector2i(250, 250);
28}
29
30void 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
42void 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
79void GLCanvas::save(Serializer &s) const {
80 Widget::save(s);
81 s.set("backgroundColor", mBackgroundColor);
82 s.set("drawBorder", mDrawBorder);
83}
84
85bool 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
92NAMESPACE_END(nanogui)
93