├── .appveyor.yml ├── .gitignore ├── .gitmodules ├── .travis.yml ├── CMakeLists.txt ├── CONTRIBUTING.rst ├── LICENSE.txt ├── README.rst ├── docs ├── Makefile ├── _static │ ├── entypo.css │ ├── entypo.eot │ ├── entypo.svg │ ├── entypo.ttf │ ├── entypo.woff │ └── entypo.woff2 ├── compilation.rst ├── conf.py ├── contributing.rst ├── examples.rst ├── index.rst ├── make.bat ├── mkdoc_rst.py ├── requirements.txt └── usage.rst ├── ext ├── coro │ ├── LICENSE │ ├── README │ ├── coro.c │ └── coro.h └── glad │ ├── include │ ├── KHR │ │ └── khrplatform.h │ └── glad │ │ └── glad.h │ └── src │ └── glad.c ├── include └── nanogui │ ├── button.h │ ├── checkbox.h │ ├── colorpicker.h │ ├── colorwheel.h │ ├── combobox.h │ ├── common.h │ ├── entypo.h │ ├── formhelper.h │ ├── glcanvas.h │ ├── glutil.h │ ├── graph.h │ ├── imagepanel.h │ ├── imageview.h │ ├── label.h │ ├── layout.h │ ├── messagedialog.h │ ├── nanogui.h │ ├── object.h │ ├── opengl.h │ ├── popup.h │ ├── popupbutton.h │ ├── progressbar.h │ ├── python.h │ ├── screen.h │ ├── serializer │ ├── core.h │ ├── opengl.h │ └── sparse.h │ ├── slider.h │ ├── stackedwidget.h │ ├── tabheader.h │ ├── tabwidget.h │ ├── textbox.h │ ├── theme.h │ ├── toolbutton.h │ ├── vscrollpanel.h │ ├── widget.h │ └── window.h ├── python ├── basics.cpp ├── button.cpp ├── constants_entypo.cpp ├── constants_glfw.cpp ├── eigen.cpp ├── example1.py ├── example2.py ├── example3.py ├── example4.py ├── example_icons.py ├── formhelper.cpp ├── glcanvas.cpp ├── glutil.cpp ├── layout.cpp ├── main.cpp ├── misc.cpp ├── nanovg.cpp ├── py_doc.h ├── python.h ├── tabs.cpp ├── textbox.cpp ├── theme.cpp └── widget.cpp ├── resources ├── Roboto-Bold.ttf ├── Roboto-Regular.ttf ├── bin2c.cmake ├── check-style.sh ├── entypo.ttf ├── icons │ ├── icon1.png │ ├── icon2.png │ ├── icon3.png │ ├── icon4.png │ ├── icon5.png │ ├── icon6.ico │ ├── icon6.png │ ├── icon7.png │ └── icon8.png ├── screenshot.png └── screenshot2.png └── src ├── button.cpp ├── checkbox.cpp ├── colorpicker.cpp ├── colorwheel.cpp ├── combobox.cpp ├── common.cpp ├── darwin.mm ├── example1.cpp ├── example2.cpp ├── example3.cpp ├── example4.cpp ├── example_icons.cpp ├── glcanvas.cpp ├── glutil.cpp ├── graph.cpp ├── imagepanel.cpp ├── imageview.cpp ├── label.cpp ├── layout.cpp ├── messagedialog.cpp ├── popup.cpp ├── popupbutton.cpp ├── progressbar.cpp ├── screen.cpp ├── serializer.cpp ├── slider.cpp ├── stackedwidget.cpp ├── tabheader.cpp ├── tabwidget.cpp ├── textbox.cpp ├── theme.cpp ├── vscrollpanel.cpp ├── widget.cpp └── window.cpp /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | os: Visual Studio 2015 3 | test: off 4 | clone_folder: C:\projects\nanogui 5 | branches: 6 | only: 7 | - master 8 | install: 9 | - git submodule update --init --recursive 10 | - cinstall: python 11 | build_script: 12 | - echo Running cmake... 13 | - cd c:\projects\nanogui 14 | - cmake -G "Visual Studio 14 2015 Win64" -DPYTHON_EXECUTABLE:FILEPATH=C:/Python34-x64/python.exe . 15 | - set MSBuildLogger="C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 16 | - set MSBuildOptions=/v:m /p:Configuration=Release /logger:%MSBuildLogger% 17 | - msbuild %MSBuildOptions% nanogui.sln 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ext/pybind11*.a 2 | *.exe 3 | *.lib 4 | *.cmake 5 | .DS_Store 6 | ext_build 7 | nanogui_resources.* 8 | build 9 | CMakeCache.txt 10 | CMakeFiles 11 | .ninja_deps 12 | .ninja_log 13 | build.ninja 14 | rules.ninja 15 | Makefile 16 | bin2c 17 | example[1-9] 18 | example_icons 19 | icons 20 | *~ 21 | nanogui*.so 22 | nanogui*.pyd 23 | libnanogui.so 24 | libnanogui.dylib 25 | .vscode/ 26 | # html documentation specific 27 | *.pyc 28 | docs/_build 29 | docs/_doxygen 30 | docs/api 31 | 32 | # entypo update generation 33 | # this is it's own repo: https://github.com/svenevs/nanogui-entypo 34 | # should not ever be needed again unless there are new 35 | # icons added :) 36 | resources/nanogui-entypo 37 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext/nanovg"] 2 | path = ext/nanovg 3 | url = https://github.com/wjakob/nanovg 4 | [submodule "ext/glfw"] 5 | path = ext/glfw 6 | url = https://github.com/wjakob/glfw 7 | [submodule "ext/eigen"] 8 | path = ext/eigen 9 | url = https://github.com/eigenteam/eigen-git-mirror.git 10 | shallow = true 11 | [submodule "ext/pybind"] 12 | path = ext/pybind11 13 | url = https://github.com/pybind/pybind11 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | dist: trusty 3 | sudo: false 4 | 5 | # Only build master branch, other branches will have a Pull Request build. 6 | branches: 7 | only: 8 | - master 9 | 10 | matrix: 11 | include: 12 | - os: linux 13 | compiler: gcc-4.8 14 | addons: 15 | apt: 16 | sources: 17 | - ubuntu-toolchain-r-test 18 | - deadsnakes 19 | - kubuntu-backports 20 | packages: 21 | - g++-4.8 22 | - python3.5 23 | - python3.5-dev 24 | - python3.5-venv 25 | - libglu1-mesa-dev 26 | - libxxf86vm-dev 27 | - libxrandr-dev 28 | - libxinerama-dev 29 | - libxcursor-dev 30 | - libxi-dev 31 | - libx11-dev 32 | - cmake 33 | script: 34 | - cmake --version 35 | - cmake -DNANOGUI_USE_GLAD=ON -DNANOGUI_PYTHON_VERSION=3.5 -DPYTHON_INCLUDE_DIRS:PATH=/usr/include/python3.5m -DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.5m.so -DCMAKE_CXX_COMPILER=g++-4.8 -DCMAKE_C_COMPILER=gcc-4.8 36 | - make -j 2 37 | - os: osx 38 | compiler: clang 39 | script: 40 | - cmake --version 41 | - cmake -DNANOGUI_PYTHON_VERSION=2.7 42 | - make -j 2 43 | - os: linux 44 | language: docs 45 | env: STYLE 46 | script: 47 | - resources/check-style.sh 48 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | Contributing 2 | ======================================================================================== 3 | 4 | Thank you for your interest in this project! Please refer to the following sections on 5 | how to contribute code and bug reports. 6 | 7 | Reporting bugs 8 | ---------------------------------------------------------------------------------------- 9 | 10 | At the moment, this project is run in the spare time of a single person 11 | (`Wenzel Jakob `_) with very limited resources for 12 | issue tracker tickets. Thus, before submitting a question or bug report, please take a 13 | moment of your time and ensure that your issue isn't already discussed in the project 14 | documentation elsewhere on this site. 15 | 16 | Feature requests are generally closed unless they come with a pull request 17 | that implements the desired functionality. 18 | 19 | Assuming that you have identified a previously unknown problem or an important question, 20 | it's essential that you submit a self-contained and minimal piece of code that 21 | reproduces the problem. In other words: no external dependencies, isolate the 22 | function(s) that cause breakage, submit matched and complete C++ or Python snippets 23 | (depending on how you are using NanoGUI) that can be easily compiled and run on my end. 24 | 25 | Pull requests 26 | ---------------------------------------------------------------------------------------- 27 | Contributions are submitted, reviewed, and accepted using Github pull requests. Please 28 | refer to `this article `_ for 29 | details and adhere to the following rules to make the process as smooth as possible: 30 | 31 | - Make a new branch for every feature you're working on. 32 | - Make small and clean pull requests that are easy to review but make sure they do add 33 | value by themselves. 34 | - Make sure you have tested any new functionality (e.g. if you made a new Widget). 35 | - This project has a strong focus on providing general solutions using a minimal amount 36 | of code, thus small pull requests are greatly preferred. 37 | - Read the remainder of this document, adhering to the bindings and documentation 38 | requirements. 39 | - If making a purely documentation PR, please prefix the commit with ``[docs]`` 40 | 41 | - E.g. ``[docs] Adding documentation for class X.`` 42 | 43 | 44 | Specific activities for contributions 45 | ---------------------------------------------------------------------------------------- 46 | 47 | For a list of specific parts of nanogui which would benefit from outside contributions, 48 | refer to the bottom part of `this page `_. 49 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Wenzel Jakob , All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors 14 | may be used to endorse or promote products derived from this software 15 | without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | You are under no obligation whatsoever to provide any bug fixes, patches, or 29 | upgrades to the features, functionality or performance of the source code 30 | ("Enhancements") to anyone; however, if you choose to make your Enhancements 31 | available either publicly, or directly to the author of this software, without 32 | imposing a separate written license agreement for such Enhancements, then you 33 | hereby grant the following license: a non-exclusive, royalty-free perpetual 34 | license to install, use, modify, prepare derivative works, incorporate into 35 | other computer software, distribute, and sublicense such enhancements or 36 | derivative works thereof, in binary and source code form. 37 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = NanoGUI 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile clean 16 | 17 | clean: 18 | rm -rf _doxygen/ api/ 19 | @$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 20 | 21 | # Catch-all target: route all unknown targets to Sphinx using the new 22 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 23 | %: Makefile 24 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 25 | -------------------------------------------------------------------------------- /docs/_static/entypo.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/docs/_static/entypo.eot -------------------------------------------------------------------------------- /docs/_static/entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/docs/_static/entypo.ttf -------------------------------------------------------------------------------- /docs/_static/entypo.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/docs/_static/entypo.woff -------------------------------------------------------------------------------- /docs/_static/entypo.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/docs/_static/entypo.woff2 -------------------------------------------------------------------------------- /docs/examples.rst: -------------------------------------------------------------------------------- 1 | .. _nanogui_example_programs: 2 | 3 | Examples 4 | ======================================================================================== 5 | 6 | There are example programs available for you to play with / understand how the different 7 | pieces fit together. The C++ examples are in ``nanogui/src/``, and the equivalent 8 | Python examples are in ``nanogui/python``. 9 | 10 | .. _nanogui_example_1: 11 | 12 | Example 1 13 | ---------------------------------------------------------------------------------------- 14 | 15 | .. image:: ../resources/screenshot.png 16 | :alt: Screenshot of Example 1. 17 | :align: center 18 | 19 | The first example program is rather long, but not altogether complicated. It 20 | is effectively an enumeration of how one would go about adding various different kinds 21 | of Widgets to the window being displayed. 22 | 23 | - `Example 1 in C++ `_ 24 | - `Example 1 in Python `_ 25 | 26 | .. _nanogui_example_2: 27 | 28 | Example 2 29 | ---------------------------------------------------------------------------------------- 30 | 31 | .. image:: ../resources/screenshot2.png 32 | :alt: Screenshot of Example 2. 33 | :align: center 34 | 35 | The second program demonstrates how simple label/editor widget-type layouts can 36 | be written in a very concise manner. 37 | 38 | - `Example 2 in C++ `_ 39 | - `Example 2 in Python `_ 40 | 41 | .. _nanogui_example_3: 42 | 43 | Example 3 44 | ---------------------------------------------------------------------------------------- 45 | 46 | The third example program demonstrates how to manage OpenGL / GLFW on your own for the 47 | C++ side, and how to detach the NanoGUI ``mainloop()`` on the Python side. 48 | 49 | - `Example 3 in C++ `_ 50 | - `Example 3 in Python `_ 51 | 52 | .. _nanogui_example_4: 53 | 54 | Example 4 55 | ---------------------------------------------------------------------------------------- 56 | 57 | The fourth example program demonstrates the GLCanvas widget, which renders an 58 | arbitrary sequence of OpenGL commands into a NanoGUI widget. 59 | 60 | - `Example 4 in C++ `_ 61 | - `Example 4 in Python `_ 62 | 63 | .. _nanogui_example_icons: 64 | 65 | Example Icons 66 | ---------------------------------------------------------------------------------------- 67 | 68 | NanoGUI includes various icons made available from :ref:`file_nanogui_entypo.h`, 69 | courtesy of `Daniel Bruce's Entypo `_ glyphs. The file level 70 | documentation is useful as a reference for selecting an icon, but the web rendering may 71 | be misleading --- NanoGUI uses a dark background for widgets by default. 72 | 73 | Run the ``exampleIcon`` executable to see what the icons look like in NanoGUI. The 74 | setup of this file may also be helpful in understanding how to control the 75 | :class:`nanogui::VScrollPanel`. 76 | 77 | - `Example Icons in C++ `_ 78 | - `Example Icons in Python `_ 79 | 80 | 81 | .. _nanogui_example_repository: 82 | 83 | Example Repository 84 | ---------------------------------------------------------------------------------------- 85 | 86 | Darren Mothersele has put together a compact and informative example repository that 87 | demonstrates how easy it is to include NanoGUI into your project. You download / browse 88 | the source on `GitHub `_. 89 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | NanoGUI 2 | ======================================================================================== 3 | 4 | .. include:: ../README.rst 5 | :start-after: begin_brief_description 6 | :end-before: end_brief_description 7 | 8 | Example Screenshot 9 | ---------------------------------------------------------------------------------------- 10 | 11 | .. image:: ../resources/screenshot.png 12 | :alt: Screenshot of Example 1. 13 | :align: center 14 | 15 | Description 16 | ---------------------------------------------------------------------------------------- 17 | 18 | .. include:: ../README.rst 19 | :start-after: begin_long_description 20 | :end-before: end_long_description 21 | 22 | "Simple mode" 23 | ---------------------------------------------------------------------------------------- 24 | 25 | Christian Schüller contributed a convenience class that makes it possible to create 26 | AntTweakBar-style variable manipulators using just a few lines of code. Refer to 27 | :ref:`nanogui_example_2` for how to create the image below. 28 | 29 | .. image:: ../resources/screenshot2.png 30 | :alt: Screenshot of Example 2. 31 | :align: center 32 | 33 | License 34 | ---------------------------------------------------------------------------------------- 35 | 36 | .. include:: ../README.rst 37 | :start-after: begin_license 38 | :end-before: end_license 39 | 40 | .. note:: 41 | 42 | The CC BY-SA 4.0 license should not be an issue for most projects. However, you can 43 | adopt a different font for icons if you need. See :ref:`nanogui_including_custom_fonts`. 44 | 45 | Contents 46 | ======================================================================================== 47 | 48 | .. toctree:: 49 | :maxdepth: 2 50 | 51 | usage 52 | compilation 53 | examples 54 | api/library_root 55 | contributing 56 | 57 | 58 | Indices and tables 59 | ================== 60 | 61 | * :ref:`genindex` 62 | * :ref:`modindex` 63 | * :ref:`search` 64 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=python -msphinx 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=NanoGUI 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed, 20 | echo.then set the SPHINXBUILD environment variable to point to the full 21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the 22 | echo.Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | Sphinx>=2.0 2 | breathe>=4.13 3 | exhale 4 | sphinx_rtd_theme 5 | -------------------------------------------------------------------------------- /docs/usage.rst: -------------------------------------------------------------------------------- 1 | Usage 2 | ======================================================================================== 3 | 4 | C++ 5 | ---------------------------------------------------------------------------------------- 6 | 7 | There are effectively two ways that you can use NanoGUI in C++: have NanoGUI initialize 8 | and manage the OpenGL context (and GLFW), or you do it manually. 9 | 10 | 1. If you are letting NanoGUI take over, you **must** call :func:`nanogui::init` 11 | before trying to do anything else. If you are managing OpenGL / GLFW yourself, make 12 | sure you **avoid** calling this method. 13 | 14 | 2. Create an instance of :class:`nanogui::Screen` (or a derivative class you have 15 | written). 16 | 17 | - NanoGUI managed OpenGL: call the explicit constructor. 18 | - Self managed OpenGL: call the empty constructor. 19 | - You must call the :func:`nanogui::Screen::initialize` method. 20 | 21 | 3. Add any Widgets, Buttons, etc. you want to the screen instance, and call the 22 | :func:`nanogui::Screen::setVisible` and :func:`nanogui::Screen::performLayout` 23 | methods of your instance. 24 | 25 | 4. Now that everything is ready, call :func:`nanogui::mainloop`. 26 | 27 | 5. When all windows are closed, this function will exit, and you should follow it up 28 | with a call to :func:`nanogui::shutdown`. 29 | 30 | :NanoGUI Managed OpenGL / GLFW: 31 | Refer to :ref:`nanogui_example_2` for a concise example of what that all looks like. 32 | 33 | :Self Managed OpenGL / GLFW: 34 | Refer to :ref:`nanogui_example_3` for an as concise as possible example of what you 35 | will need to do to get the :class:`nanogui::Screen` to work. 36 | 37 | 38 | Python 39 | ---------------------------------------------------------------------------------------- 40 | 41 | The Python interface is very similar to the C++ API. When you build NanoGUI with CMake, 42 | a ``python`` folder is created with the library you ``import nanogui`` from. Though 43 | there are implementation details that differ greatly, the documentation and build 44 | process for the Python side is roughly the same. Refer to the 45 | :ref:`nanogui_example_programs` and compare the source code for the two. 46 | 47 | :ref:`nanogui_example_3` highlights the more notable differences between the APIs. 48 | Specifically, that managing GLFW from Python has no meaning, as well as the main loop 49 | for Python can easily be detached. 50 | -------------------------------------------------------------------------------- /ext/coro/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2000-2009 Marc Alexander Lehmann 2 | 3 | Redistribution and use in source and binary forms, with or without modifica- 4 | tion, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 15 | CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 16 | EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 17 | CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 19 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 21 | ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 22 | OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | Alternatively, the following files carry an additional notice that 25 | explicitly allows relicensing under the GPLv2: coro.c, coro.h. 26 | 27 | -------------------------------------------------------------------------------- /ext/coro/README: -------------------------------------------------------------------------------- 1 | Configuration, documentation etc. is provided in the coro.h file. Please 2 | note that the file conftest.c in this distribution is under the GPL. It is 3 | not needed for proper operation of this library though, for that, coro.h 4 | and coro.c suffice. 5 | 6 | Marc Lehmann 7 | -------------------------------------------------------------------------------- /include/nanogui/checkbox.h: -------------------------------------------------------------------------------- 1 | /* 2 | NanoGUI was developed by Wenzel Jakob . 3 | The widget drawing code is based on the NanoVG demo application 4 | by Mikko Mononen. 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE.txt file. 8 | */ 9 | /** 10 | * \file nanogui/checkbox.h 11 | * 12 | * \brief Two-state check box Widget. 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | 19 | NAMESPACE_BEGIN(nanogui) 20 | 21 | /** 22 | * \class CheckBox checkbox.h nanogui/checkbox.h 23 | * 24 | * \brief Two-state check box widget. 25 | * 26 | * \remark 27 | * This class overrides \ref nanogui::Widget::mIconExtraScale to be ``1.2f``, 28 | * which affects all subclasses of this Widget. Subclasses must explicitly 29 | * set a different value if needed (e.g., in their constructor). 30 | */ 31 | class NANOGUI_EXPORT CheckBox : public Widget { 32 | public: 33 | /** 34 | * Adds a CheckBox to the specified ``parent``. 35 | * 36 | * \param parent 37 | * The Widget to add this CheckBox to. 38 | * 39 | * \param caption 40 | * The caption text of the CheckBox (default ``"Untitled"``). 41 | * 42 | * \param callback 43 | * If provided, the callback to execute when the CheckBox is checked or 44 | * unchecked. Default parameter function does nothing. See 45 | * \ref nanogui::CheckBox::mPushed for the difference between "pushed" 46 | * and "checked". 47 | */ 48 | CheckBox(Widget *parent, const std::string &caption = "Untitled", 49 | const std::function &callback = std::function()); 50 | 51 | /// The caption of this CheckBox. 52 | const std::string &caption() const { return mCaption; } 53 | 54 | /// Sets the caption of this CheckBox. 55 | void setCaption(const std::string &caption) { mCaption = caption; } 56 | 57 | /// Whether or not this CheckBox is currently checked. 58 | const bool &checked() const { return mChecked; } 59 | 60 | /// Sets whether or not this CheckBox is currently checked. 61 | void setChecked(const bool &checked) { mChecked = checked; } 62 | 63 | /// Whether or not this CheckBox is currently pushed. See \ref nanogui::CheckBox::mPushed. 64 | const bool &pushed() const { return mPushed; } 65 | 66 | /// Sets whether or not this CheckBox is currently pushed. See \ref nanogui::CheckBox::mPushed. 67 | void setPushed(const bool &pushed) { mPushed = pushed; } 68 | 69 | /// Returns the current callback of this CheckBox. 70 | std::function callback() const { return mCallback; } 71 | 72 | /// Sets the callback to be executed when this CheckBox is checked / unchecked. 73 | void setCallback(const std::function &callback) { mCallback = callback; } 74 | 75 | /** 76 | * The mouse button callback will return ``true`` when all three conditions are met: 77 | * 78 | * 1. This CheckBox is "enabled" (see \ref nanogui::Widget::mEnabled). 79 | * 2. ``p`` is inside this CheckBox. 80 | * 3. ``button`` is ``GLFW_MOUSE_BUTTON_1`` (left mouse click). 81 | * 82 | * Since a mouse button event is issued for both when the mouse is pressed, as well 83 | * as released, this function sets \ref nanogui::CheckBox::mPushed to ``true`` when 84 | * parameter ``down == true``. When the second event (``down == false``) is fired, 85 | * \ref nanogui::CheckBox::mChecked is inverted and \ref nanogui::CheckBox::mCallback 86 | * is called. 87 | * 88 | * That is, the callback provided is only called when the mouse button is released, 89 | * **and** the click location remains within the CheckBox boundaries. If the user 90 | * clicks on the CheckBox and releases away from the bounds of the CheckBox, 91 | * \ref nanogui::CheckBox::mPushed is simply set back to ``false``. 92 | */ 93 | virtual bool mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers) override; 94 | 95 | /// The preferred size of this CheckBox. 96 | virtual Vector2i preferredSize(NVGcontext *ctx) const override; 97 | 98 | /// Draws this CheckBox. 99 | virtual void draw(NVGcontext *ctx) override; 100 | 101 | /// Saves this CheckBox to the specified Serializer. 102 | virtual void save(Serializer &s) const override; 103 | 104 | /// Loads the state of the specified Serializer to this CheckBox. 105 | virtual bool load(Serializer &s) override; 106 | 107 | protected: 108 | /// The caption text of this CheckBox. 109 | std::string mCaption; 110 | 111 | /** 112 | * Internal tracking variable to distinguish between mouse click and release. 113 | * \ref nanogui::CheckBox::mCallback is only called upon release. See 114 | * \ref nanogui::CheckBox::mouseButtonEvent for specific conditions. 115 | */ 116 | bool mPushed; 117 | 118 | /// Whether or not this CheckBox is currently checked or unchecked. 119 | bool mChecked; 120 | 121 | /// The function to execute when \ref nanogui::CheckBox::mChecked is changed. 122 | std::function mCallback; 123 | 124 | public: 125 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 126 | }; 127 | 128 | NAMESPACE_END(nanogui) 129 | -------------------------------------------------------------------------------- /include/nanogui/colorpicker.h: -------------------------------------------------------------------------------- 1 | /* 2 | NanoGUI was developed by Wenzel Jakob . 3 | The widget drawing code is based on the NanoVG demo application 4 | by Mikko Mononen. 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE.txt file. 8 | */ 9 | /** 10 | * \file nanogui/colorpicker.h 11 | * 12 | * \brief Push button with a popup to tweak a color value. This widget was 13 | * contributed by Christian Schueller. 14 | */ 15 | 16 | #pragma once 17 | 18 | #include 19 | 20 | NAMESPACE_BEGIN(nanogui) 21 | 22 | /** 23 | * \class ColorPicker colorpicker.h nanogui/colorpicker.h 24 | * 25 | * \brief Push button with a popup to tweak a color value. This widget was 26 | * contributed by Christian Schueller. 27 | */ 28 | class NANOGUI_EXPORT ColorPicker : public PopupButton { 29 | public: 30 | /** 31 | * Attaches a ColorPicker to the specified parent. 32 | * 33 | * \param parent 34 | * The Widget to add this ColorPicker to. 35 | * 36 | * \param color 37 | * The color initially selected by this ColorPicker (default: Red). 38 | */ 39 | ColorPicker(Widget *parent, const Color& color = Color(1.0f, 0.0f, 0.0f, 1.0f)); 40 | 41 | /// The callback executed when the ColorWheel changes. 42 | std::function callback() const { return mCallback; } 43 | 44 | /** 45 | * Sets the callback is executed as the ColorWheel itself is changed. Set 46 | * this callback if you need to receive updates for the ColorWheel changing 47 | * before the user clicks \ref nanogui::ColorPicker::mPickButton or 48 | * \ref nanogui::ColorPicker::mPickButton. 49 | */ 50 | void setCallback(const std::function &callback) { 51 | mCallback = callback; 52 | mCallback(backgroundColor()); 53 | } 54 | 55 | /** 56 | * The callback to execute when a new Color is selected on the ColorWheel 57 | * **and** the user clicks the \ref nanogui::ColorPicker::mPickButton or 58 | * \ref nanogui::ColorPicker::mResetButton. 59 | */ 60 | std::function finalCallback() const { return mFinalCallback; } 61 | 62 | /** 63 | * The callback to execute when a new Color is selected on the ColorWheel 64 | * **and** the user clicks the \ref nanogui::ColorPicker::mPickButton or 65 | * \ref nanogui::ColorPicker::mResetButton. 66 | */ 67 | void setFinalCallback(const std::function &callback) { mFinalCallback = callback; } 68 | 69 | /// Get the current Color selected for this ColorPicker. 70 | Color color() const; 71 | 72 | /// Set the current Color selected for this ColorPicker. 73 | void setColor(const Color& color); 74 | 75 | /// The current caption of the \ref nanogui::ColorPicker::mPickButton. 76 | const std::string &pickButtonCaption() { return mPickButton->caption(); } 77 | 78 | /// Sets the current caption of the \ref nanogui::ColorPicker::mPickButton. 79 | void setPickButtonCaption(const std::string &caption) { mPickButton->setCaption(caption); } 80 | 81 | /// The current caption of the \ref nanogui::ColorPicker::mResetButton. 82 | const std::string &resetButtonCaption() { return mResetButton->caption(); } 83 | 84 | /// Sets the current caption of the \ref nanogui::ColorPicker::mResetButton. 85 | void setResetButtonCaption(const std::string &caption) { mResetButton->setCaption(caption); } 86 | 87 | protected: 88 | /// The "fast" callback executed when the ColorWheel has changed. 89 | std::function mCallback; 90 | 91 | /** 92 | * The callback to execute when a new Color is selected on the ColorWheel 93 | * **and** the user clicks the \ref nanogui::ColorPicker::mPickButton or 94 | * \ref nanogui::ColorPicker::mResetButton. 95 | */ 96 | std::function mFinalCallback; 97 | 98 | /// The ColorWheel for this ColorPicker (the actual widget allowing selection). 99 | ColorWheel *mColorWheel; 100 | 101 | /** 102 | * The Button used to signal that the current value on the ColorWheel is the 103 | * desired color to be chosen. The default value for the caption of this 104 | * Button is ``"Pick"``. You can change it using 105 | * \ref nanogui::ColorPicker::setPickButtonCaption if you need. 106 | * 107 | * The color of this Button will not affect \ref nanogui::ColorPicker::color 108 | * until the user has actively selected by clicking this pick button. 109 | * Similarly, the \ref nanogui::ColorPicker::mCallback function is only 110 | * called when a user selects a new Color using by clicking this Button. 111 | */ 112 | Button *mPickButton; 113 | 114 | /** 115 | * Remains the Color of the active color selection, until the user picks a 116 | * new Color on the ColorWheel **and** selects the 117 | * \ref nanogui::ColorPicker::mPickButton. The default value for the 118 | * caption of this Button is ``"Reset"``. You can change it using 119 | * \ref nanogui::ColorPicker::setResetButtonCaption if you need. 120 | */ 121 | Button *mResetButton; 122 | 123 | public: 124 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 125 | }; 126 | 127 | NAMESPACE_END(nanogui) 128 | -------------------------------------------------------------------------------- /include/nanogui/colorwheel.h: -------------------------------------------------------------------------------- 1 | /* 2 | NanoGUI was developed by Wenzel Jakob . 3 | The widget drawing code is based on the NanoVG demo application 4 | by Mikko Mononen. 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE.txt file. 8 | */ 9 | /** 10 | * \file nanogui/colorwheel.h 11 | * 12 | * \brief Fancy analog widget to select a color value. This widget was 13 | * contributed by Dmitriy Morozov. 14 | */ 15 | 16 | #pragma once 17 | 18 | #include 19 | 20 | NAMESPACE_BEGIN(nanogui) 21 | 22 | /** 23 | * \class ColorWheel colorwheel.h nanogui/colorwheel.h 24 | * 25 | * \brief Fancy analog widget to select a color value. This widget was 26 | * contributed by Dmitriy Morozov. 27 | */ 28 | class NANOGUI_EXPORT ColorWheel : public Widget { 29 | public: 30 | /** 31 | * Adds a ColorWheel to the specified parent. 32 | * 33 | * \param parent 34 | * The Widget to add this ColorWheel to. 35 | * 36 | * \param color 37 | * The initial color of the ColorWheel (default: Red). 38 | */ 39 | ColorWheel(Widget *parent, const Color& color = Color(1.0f, 0.0f, 0.0f, 1.0f)); 40 | 41 | /// The callback to execute when a user changes the ColorWheel value. 42 | std::function callback() const { return mCallback; } 43 | 44 | /// Sets the callback to execute when a user changes the ColorWheel value. 45 | void setCallback(const std::function &callback) { mCallback = callback; } 46 | 47 | /// The current Color this ColorWheel has selected. 48 | Color color() const; 49 | 50 | /// Sets the current Color this ColorWheel has selected. 51 | void setColor(const Color& color); 52 | 53 | /// The preferred size of this ColorWheel. 54 | virtual Vector2i preferredSize(NVGcontext *ctx) const override; 55 | 56 | /// Draws the ColorWheel. 57 | virtual void draw(NVGcontext *ctx) override; 58 | 59 | /// Handles mouse button click events for the ColorWheel. 60 | virtual bool mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers) override; 61 | 62 | /// Handles mouse drag events for the ColorWheel. 63 | virtual bool mouseDragEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override; 64 | 65 | /// Saves the current state of this ColorWheel to the specified Serializer. 66 | virtual void save(Serializer &s) const override; 67 | 68 | /// Sets the state of this ColorWheel using the specified Serializer. 69 | virtual bool load(Serializer &s) override; 70 | 71 | private: 72 | // Used to describe where the mouse is interacting 73 | enum Region { 74 | None = 0, 75 | InnerTriangle = 1, 76 | OuterCircle = 2, 77 | Both = 3 78 | }; 79 | 80 | // Converts a specified hue (with saturation = value = 1) to RGB space. 81 | Color hue2rgb(float h) const; 82 | 83 | // Manipulates the positioning of the different regions of the ColorWheel. 84 | Region adjustPosition(const Vector2i &p, Region consideredRegions = Both); 85 | 86 | protected: 87 | /// The current Hue in the HSV color model. 88 | float mHue; 89 | 90 | /** 91 | * The implicit Value component of the HSV color model. See implementation 92 | * \ref nanogui::ColorWheel::color for its usage. Valid values are in the 93 | * range ``[0, 1]``. 94 | */ 95 | float mWhite; 96 | 97 | /** 98 | * The implicit Saturation component of the HSV color model. See implementation 99 | * \ref nanogui::ColorWheel::color for its usage. Valid values are in the 100 | * range ``[0, 1]``. 101 | */ 102 | float mBlack; 103 | 104 | /// The current region the mouse is interacting with. 105 | Region mDragRegion; 106 | 107 | /// The current callback to execute when the color value has changed. 108 | std::function mCallback; 109 | 110 | public: 111 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 112 | }; 113 | 114 | NAMESPACE_END(nanogui) 115 | -------------------------------------------------------------------------------- /include/nanogui/combobox.h: -------------------------------------------------------------------------------- 1 | /* 2 | NanoGUI was developed by Wenzel Jakob . 3 | The widget drawing code is based on the NanoVG demo application 4 | by Mikko Mononen. 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE.txt file. 8 | */ 9 | /** 10 | * \file nanogui/combobox.h 11 | * 12 | * \brief Simple combo box widget based on a popup button. 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | 19 | NAMESPACE_BEGIN(nanogui) 20 | 21 | /** 22 | * \class ComboBox combobox.h nanogui/combobox.h 23 | * 24 | * \brief Simple combo box widget based on a popup button. 25 | */ 26 | class NANOGUI_EXPORT ComboBox : public PopupButton { 27 | public: 28 | /// Create an empty combo box 29 | ComboBox(Widget *parent); 30 | 31 | /// Create a new combo box with the given items 32 | ComboBox(Widget *parent, const std::vector &items); 33 | 34 | /** 35 | * \brief Create a new combo box with the given items, providing both short and 36 | * long descriptive labels for each item 37 | */ 38 | ComboBox(Widget *parent, const std::vector &items, 39 | const std::vector &itemsShort); 40 | 41 | /// The callback to execute for this ComboBox. 42 | std::function callback() const { return mCallback; } 43 | 44 | /// Sets the callback to execute for this ComboBox. 45 | void setCallback(const std::function &callback) { mCallback = callback; } 46 | 47 | /// The current index this ComboBox has selected. 48 | int selectedIndex() const { return mSelectedIndex; } 49 | 50 | /// Sets the current index this ComboBox has selected. 51 | void setSelectedIndex(int idx); 52 | 53 | /// Sets the items for this ComboBox, providing both short and long descriptive lables for each item. 54 | void setItems(const std::vector &items, const std::vector &itemsShort); 55 | 56 | /// Sets the items for this ComboBox. 57 | void setItems(const std::vector &items) { setItems(items, items); } 58 | 59 | /// The items associated with this ComboBox. 60 | const std::vector &items() const { return mItems; } 61 | 62 | /// The short descriptions associated with this ComboBox. 63 | const std::vector &itemsShort() const { return mItemsShort; } 64 | 65 | /// Handles mouse scrolling events for this ComboBox. 66 | virtual bool scrollEvent(const Vector2i &p, const Vector2f &rel) override; 67 | 68 | /// Saves the state of this ComboBox to the specified Serializer. 69 | virtual void save(Serializer &s) const override; 70 | 71 | /// Sets the state of this ComboBox from the specified Serializer. 72 | virtual bool load(Serializer &s) override; 73 | 74 | protected: 75 | /// The items associated with this ComboBox. 76 | std::vector mItems; 77 | 78 | /// The short descriptions of items associated with this ComboBox. 79 | std::vector mItemsShort; 80 | 81 | /// The callback for this ComboBox. 82 | std::function mCallback; 83 | 84 | /// The current index this ComboBox has selected. 85 | int mSelectedIndex; 86 | 87 | public: 88 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 89 | }; 90 | 91 | NAMESPACE_END(nanogui) 92 | -------------------------------------------------------------------------------- /include/nanogui/glcanvas.h: -------------------------------------------------------------------------------- 1 | /* 2 | NanoGUI was developed by Wenzel Jakob . 3 | The widget drawing code is based on the NanoVG demo application 4 | by Mikko Mononen. 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE.txt file. 8 | */ 9 | /** 10 | * \file nanogui/glcanvas.h 11 | * 12 | * \brief Canvas widget for rendering OpenGL content. This widget was 13 | * contributed by Jan Winkler. 14 | */ 15 | 16 | #pragma once 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | NAMESPACE_BEGIN(nanogui) 25 | 26 | /** 27 | * \class GLCanvas glcanvas.h nanogui/glcanvas.h 28 | * 29 | * \brief Canvas widget for rendering OpenGL content. This widget was 30 | * contributed by Jan Winkler. 31 | * 32 | * Canvas widget that can be used to display arbitrary OpenGL content. This is 33 | * useful to display and manipulate 3D objects as part of an interactive 34 | * application. The implementation uses scissoring to ensure that rendered 35 | * objects don't spill into neighboring widgets. 36 | * 37 | * \rst 38 | * **Usage** 39 | * Override :func:`nanogui::GLCanvas::drawGL` in subclasses to provide 40 | * custom drawing code. See :ref:`nanogui_example_4`. 41 | * 42 | * \endrst 43 | */ 44 | class NANOGUI_EXPORT GLCanvas : public Widget { 45 | public: 46 | /** 47 | * Creates a GLCanvas attached to the specified parent. 48 | * 49 | * \param parent 50 | * The Widget to attach this GLCanvas to. 51 | */ 52 | GLCanvas(Widget *parent); 53 | 54 | /// Returns the background color. 55 | const Color &backgroundColor() const { return mBackgroundColor; } 56 | 57 | /// Sets the background color. 58 | void setBackgroundColor(const Color &backgroundColor) { mBackgroundColor = backgroundColor; } 59 | 60 | /// Set whether to draw the widget border or not. 61 | void setDrawBorder(const bool bDrawBorder) { mDrawBorder = bDrawBorder; } 62 | 63 | /// Return whether the widget border gets drawn or not. 64 | const bool &drawBorder() const { return mDrawBorder; } 65 | 66 | /// Draw the canvas. 67 | virtual void draw(NVGcontext *ctx) override; 68 | 69 | /// Draw the GL scene. Override this method to draw the actual GL content. 70 | virtual void drawGL() {} 71 | 72 | /// Save the state of this GLCanvas to the specified Serializer. 73 | virtual void save(Serializer &s) const override; 74 | 75 | /// Set the state of this GLCanvas from the specified Serializer. 76 | virtual bool load(Serializer &s) override; 77 | 78 | protected: 79 | /// Internal helper function for drawing the widget border 80 | void drawWidgetBorder(NVGcontext* ctx) const; 81 | 82 | protected: 83 | /// The background color (what is used with ``glClearColor``). 84 | Color mBackgroundColor; 85 | 86 | /// Whether to draw the widget border or not. 87 | bool mDrawBorder; 88 | 89 | public: 90 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 91 | }; 92 | 93 | NAMESPACE_END(nanogui) 94 | -------------------------------------------------------------------------------- /include/nanogui/graph.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/graph.h -- Simple graph widget for showing a function plot 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | /** 20 | * \class Graph graph.h nanogui/graph.h 21 | * 22 | * \brief Simple graph widget for showing a function plot. 23 | */ 24 | class NANOGUI_EXPORT Graph : public Widget { 25 | public: 26 | Graph(Widget *parent, const std::string &caption = "Untitled"); 27 | 28 | const std::string &caption() const { return mCaption; } 29 | void setCaption(const std::string &caption) { mCaption = caption; } 30 | 31 | const std::string &header() const { return mHeader; } 32 | void setHeader(const std::string &header) { mHeader = header; } 33 | 34 | const std::string &footer() const { return mFooter; } 35 | void setFooter(const std::string &footer) { mFooter = footer; } 36 | 37 | const Color &backgroundColor() const { return mBackgroundColor; } 38 | void setBackgroundColor(const Color &backgroundColor) { mBackgroundColor = backgroundColor; } 39 | 40 | const Color &foregroundColor() const { return mForegroundColor; } 41 | void setForegroundColor(const Color &foregroundColor) { mForegroundColor = foregroundColor; } 42 | 43 | const Color &textColor() const { return mTextColor; } 44 | void setTextColor(const Color &textColor) { mTextColor = textColor; } 45 | 46 | const VectorXf &values() const { return mValues; } 47 | VectorXf &values() { return mValues; } 48 | void setValues(const VectorXf &values) { mValues = values; } 49 | 50 | virtual Vector2i preferredSize(NVGcontext *ctx) const override; 51 | virtual void draw(NVGcontext *ctx) override; 52 | 53 | virtual void save(Serializer &s) const override; 54 | virtual bool load(Serializer &s) override; 55 | protected: 56 | std::string mCaption, mHeader, mFooter; 57 | Color mBackgroundColor, mForegroundColor, mTextColor; 58 | VectorXf mValues; 59 | public: 60 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 61 | }; 62 | 63 | NAMESPACE_END(nanogui) 64 | -------------------------------------------------------------------------------- /include/nanogui/imagepanel.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/imagepanel.h -- Image panel widget which shows a number of 3 | square-shaped icons 4 | 5 | NanoGUI was developed by Wenzel Jakob . 6 | The widget drawing code is based on the NanoVG demo application 7 | by Mikko Mononen. 8 | 9 | All rights reserved. Use of this source code is governed by a 10 | BSD-style license that can be found in the LICENSE.txt file. 11 | */ 12 | /** \file */ 13 | 14 | #pragma once 15 | 16 | #include 17 | 18 | NAMESPACE_BEGIN(nanogui) 19 | 20 | /** 21 | * \class ImagePanel imagepanel.h nanogui/imagepanel.h 22 | * 23 | * \brief Image panel widget which shows a number of square-shaped icons. 24 | */ 25 | class NANOGUI_EXPORT ImagePanel : public Widget { 26 | public: 27 | typedef std::vector> Images; 28 | public: 29 | ImagePanel(Widget *parent); 30 | 31 | void setImages(const Images &data) { mImages = data; } 32 | const Images& images() const { return mImages; } 33 | 34 | std::function callback() const { return mCallback; } 35 | void setCallback(const std::function &callback) { mCallback = callback; } 36 | 37 | virtual bool mouseMotionEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override; 38 | virtual bool mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers) override; 39 | virtual Vector2i preferredSize(NVGcontext *ctx) const override; 40 | virtual void draw(NVGcontext* ctx) override; 41 | protected: 42 | Vector2i gridSize() const; 43 | int indexForPosition(const Vector2i &p) const; 44 | protected: 45 | Images mImages; 46 | std::function mCallback; 47 | int mThumbSize; 48 | int mSpacing; 49 | int mMargin; 50 | int mMouseIndex; 51 | public: 52 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 53 | }; 54 | 55 | NAMESPACE_END(nanogui) 56 | -------------------------------------------------------------------------------- /include/nanogui/label.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/label.h -- Text label with an arbitrary font, color, and size 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | /** 20 | * \class Label label.h nanogui/label.h 21 | * 22 | * \brief Text label widget. 23 | * 24 | * The font and color can be customized. When \ref Widget::setFixedWidth() 25 | * is used, the text is wrapped when it surpasses the specified width. 26 | */ 27 | class NANOGUI_EXPORT Label : public Widget { 28 | public: 29 | Label(Widget *parent, const std::string &caption, 30 | const std::string &font = "sans", int fontSize = -1); 31 | 32 | /// Get the label's text caption 33 | const std::string &caption() const { return mCaption; } 34 | /// Set the label's text caption 35 | void setCaption(const std::string &caption) { mCaption = caption; } 36 | 37 | /// Set the currently active font (2 are available by default: 'sans' and 'sans-bold') 38 | void setFont(const std::string &font) { mFont = font; } 39 | /// Get the currently active font 40 | const std::string &font() const { return mFont; } 41 | 42 | /// Get the label color 43 | Color color() const { return mColor; } 44 | /// Set the label color 45 | void setColor(const Color& color) { mColor = color; } 46 | 47 | /// Set the \ref Theme used to draw this widget 48 | virtual void setTheme(Theme *theme) override; 49 | 50 | /// Compute the size needed to fully display the label 51 | virtual Vector2i preferredSize(NVGcontext *ctx) const override; 52 | 53 | /// Draw the label 54 | virtual void draw(NVGcontext *ctx) override; 55 | 56 | virtual void save(Serializer &s) const override; 57 | virtual bool load(Serializer &s) override; 58 | protected: 59 | std::string mCaption; 60 | std::string mFont; 61 | Color mColor; 62 | public: 63 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 64 | }; 65 | 66 | NAMESPACE_END(nanogui) 67 | -------------------------------------------------------------------------------- /include/nanogui/messagedialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/messagedialog.h -- Simple "OK" or "Yes/No"-style modal dialogs 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | /** 20 | * \class MessageDialog messagedialog.h nanogui/messagedialog.h 21 | * 22 | * \brief Simple "OK" or "Yes/No"-style modal dialogs. 23 | */ 24 | class NANOGUI_EXPORT MessageDialog : public Window { 25 | public: 26 | /// Classification of the type of message this MessageDialog represents. 27 | enum class Type { 28 | Information, 29 | Question, 30 | Warning 31 | }; 32 | 33 | MessageDialog(Widget *parent, Type type, const std::string &title = "Untitled", 34 | const std::string &message = "Message", 35 | const std::string &buttonText = "OK", 36 | const std::string &altButtonText = "Cancel", bool altButton = false); 37 | 38 | Label *messageLabel() { return mMessageLabel; } 39 | const Label *messageLabel() const { return mMessageLabel; } 40 | 41 | std::function callback() const { return mCallback; } 42 | void setCallback(const std::function &callback) { mCallback = callback; } 43 | protected: 44 | std::function mCallback; 45 | Label *mMessageLabel; 46 | public: 47 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 48 | }; 49 | 50 | NAMESPACE_END(nanogui) 51 | -------------------------------------------------------------------------------- /include/nanogui/nanogui.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/nanogui.h -- Pull in *everything* from NanoGUI 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | -------------------------------------------------------------------------------- /include/nanogui/object.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/object.h -- Object base class with support for reference counting 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | NAMESPACE_BEGIN(nanogui) 19 | 20 | /** 21 | * \class Object object.h nanogui/object.h 22 | * 23 | * \brief Reference counted object base class. 24 | */ 25 | class NANOGUI_EXPORT Object { 26 | public: 27 | /// Default constructor 28 | Object() { } 29 | 30 | /// Copy constructor 31 | Object(const Object &) : m_refCount(0) {} 32 | 33 | /// Return the current reference count 34 | int getRefCount() const { return m_refCount; }; 35 | 36 | /// Increase the object's reference count by one 37 | void incRef() const { ++m_refCount; } 38 | 39 | /** \brief Decrease the reference count of 40 | * the object and possibly deallocate it. 41 | * 42 | * The object will automatically be deallocated once 43 | * the reference count reaches zero. 44 | */ 45 | void decRef(bool dealloc = true) const noexcept; 46 | protected: 47 | /** \brief Virtual protected deconstructor. 48 | * (Will only be called by \ref ref) 49 | */ 50 | virtual ~Object(); 51 | private: 52 | mutable std::atomic m_refCount { 0 }; 53 | }; 54 | 55 | /** 56 | * \class ref object.h nanogui/object.h 57 | * 58 | * \brief Reference counting helper. 59 | * 60 | * The \a ref template is a simple wrapper to store a pointer to an object. It 61 | * takes care of increasing and decreasing the object's reference count as 62 | * needed. When the last reference goes out of scope, the associated object 63 | * will be deallocated. 64 | * 65 | * The advantage over C++ solutions such as ``std::shared_ptr`` is that 66 | * the reference count is very compactly integrated into the base object 67 | * itself. 68 | */ 69 | template class ref { 70 | public: 71 | /// Create a ``nullptr``-valued reference 72 | ref() { } 73 | 74 | /// Construct a reference from a pointer 75 | ref(T *ptr) : m_ptr(ptr) { 76 | if (m_ptr) 77 | ((Object *) m_ptr)->incRef(); 78 | } 79 | 80 | /// Copy constructor 81 | ref(const ref &r) : m_ptr(r.m_ptr) { 82 | if (m_ptr) 83 | ((Object *) m_ptr)->incRef(); 84 | } 85 | 86 | /// Move constructor 87 | ref(ref &&r) noexcept : m_ptr(r.m_ptr) { 88 | r.m_ptr = nullptr; 89 | } 90 | 91 | /// Destroy this reference 92 | ~ref() { 93 | if (m_ptr) 94 | ((Object *) m_ptr)->decRef(); 95 | } 96 | 97 | /// Move another reference into the current one 98 | ref& operator=(ref&& r) noexcept { 99 | if (&r != this) { 100 | if (m_ptr) 101 | ((Object *) m_ptr)->decRef(); 102 | m_ptr = r.m_ptr; 103 | r.m_ptr = nullptr; 104 | } 105 | return *this; 106 | } 107 | 108 | /// Overwrite this reference with another reference 109 | ref& operator=(const ref& r) noexcept { 110 | if (m_ptr != r.m_ptr) { 111 | if (r.m_ptr) 112 | ((Object *) r.m_ptr)->incRef(); 113 | if (m_ptr) 114 | ((Object *) m_ptr)->decRef(); 115 | m_ptr = r.m_ptr; 116 | } 117 | return *this; 118 | } 119 | 120 | /// Overwrite this reference with a pointer to another object 121 | ref& operator=(T *ptr) noexcept { 122 | if (m_ptr != ptr) { 123 | if (ptr) 124 | ((Object *) ptr)->incRef(); 125 | if (m_ptr) 126 | ((Object *) m_ptr)->decRef(); 127 | m_ptr = ptr; 128 | } 129 | return *this; 130 | } 131 | 132 | /// Compare this reference with another reference 133 | bool operator==(const ref &r) const { return m_ptr == r.m_ptr; } 134 | 135 | /// Compare this reference with another reference 136 | bool operator!=(const ref &r) const { return m_ptr != r.m_ptr; } 137 | 138 | /// Compare this reference with a pointer 139 | bool operator==(const T* ptr) const { return m_ptr == ptr; } 140 | 141 | /// Compare this reference with a pointer 142 | bool operator!=(const T* ptr) const { return m_ptr != ptr; } 143 | 144 | /// Access the object referenced by this reference 145 | T* operator->() { return m_ptr; } 146 | 147 | /// Access the object referenced by this reference 148 | const T* operator->() const { return m_ptr; } 149 | 150 | /// Return a C++ reference to the referenced object 151 | T& operator*() { return *m_ptr; } 152 | 153 | /// Return a const C++ reference to the referenced object 154 | const T& operator*() const { return *m_ptr; } 155 | 156 | /// Return a pointer to the referenced object 157 | operator T* () { return m_ptr; } 158 | 159 | /// Return a const pointer to the referenced object 160 | T* get() { return m_ptr; } 161 | 162 | /// Return a pointer to the referenced object 163 | const T* get() const { return m_ptr; } 164 | 165 | /// Check if the object is defined 166 | operator bool() const { return m_ptr != nullptr; } 167 | private: 168 | T *m_ptr = nullptr; 169 | }; 170 | 171 | NAMESPACE_END(nanogui) 172 | -------------------------------------------------------------------------------- /include/nanogui/opengl.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/opengl.h -- Pulls in OpenGL, GLAD (if needed), GLFW, and 3 | NanoVG header files 4 | 5 | NanoGUI was developed by Wenzel Jakob . 6 | The widget drawing code is based on the NanoVG demo application 7 | by Mikko Mononen. 8 | 9 | All rights reserved. Use of this source code is governed by a 10 | BSD-style license that can be found in the LICENSE.txt file. 11 | */ 12 | /** \file */ 13 | 14 | #pragma once 15 | 16 | #include 17 | 18 | #ifndef DOXYGEN_SHOULD_SKIP_THIS 19 | #if defined(NANOGUI_GLAD) 20 | #if defined(NANOGUI_SHARED) && !defined(GLAD_GLAPI_EXPORT) 21 | #define GLAD_GLAPI_EXPORT 22 | #endif 23 | 24 | #include 25 | #else 26 | #if defined(__APPLE__) 27 | #define GLFW_INCLUDE_GLCOREARB 28 | #else 29 | #define GL_GLEXT_PROTOTYPES 30 | #endif 31 | #endif 32 | #endif // DOXYGEN_SHOULD_SKIP_THIS 33 | 34 | #include 35 | #include 36 | 37 | // Special treatment of linux Nvidia opengl headers 38 | #if !defined(_WIN32) && !defined(__APPLE__) 39 | #if !defined(GL_UNIFORM_BUFFER) 40 | #warning NanoGUI suspects you have the NVIDIA OpenGL headers installed. \ 41 | Compilation will likely fail. If it does, you have two choices: \ 42 | (1) Re-install the mesa-libGL header files. \ 43 | (2) Compile with NANOGUI_USE_GLAD. 44 | #endif 45 | #endif 46 | 47 | NAMESPACE_BEGIN(nanogui) 48 | 49 | /// Allows for conversion between nanogui::Color and the NanoVG NVGcolor class. 50 | inline Color::operator const NVGcolor &() const { 51 | return reinterpret_cast(*this->data()); 52 | } 53 | 54 | /** 55 | * \brief Determine whether an icon ID is a texture loaded via ``nvgImageIcon``. 56 | * 57 | * \rst 58 | * The implementation defines all ``value < 1024`` as image icons, and 59 | * everything ``>= 1024`` as an Entypo icon (see :ref:`file_nanogui_entypo.h`). 60 | * The value ``1024`` exists to provide a generous buffer on how many images 61 | * may have been loaded by NanoVG. 62 | * \endrst 63 | * 64 | * \param value 65 | * The integral value of the icon. 66 | * 67 | * \return 68 | * Whether or not this is an image icon. 69 | */ 70 | inline bool nvgIsImageIcon(int value) { return value < 1024; } 71 | 72 | /** 73 | * \brief Determine whether an icon ID is a font-based icon (e.g. from ``entypo.ttf``). 74 | * 75 | * \rst 76 | * See :func:`nanogui::nvgIsImageIcon` for details. 77 | * \endrst 78 | * 79 | * \param value 80 | * The integral value of the icon. 81 | * 82 | * \return 83 | * Whether or not this is a font icon (from ``entypo.ttf``). 84 | */ 85 | inline bool nvgIsFontIcon(int value) { return value >= 1024; } 86 | 87 | NAMESPACE_END(nanogui) 88 | -------------------------------------------------------------------------------- /include/nanogui/popup.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/popup.h -- Simple popup widget which is attached to another given 3 | window (can be nested) 4 | 5 | NanoGUI was developed by Wenzel Jakob . 6 | The widget drawing code is based on the NanoVG demo application 7 | by Mikko Mononen. 8 | 9 | All rights reserved. Use of this source code is governed by a 10 | BSD-style license that can be found in the LICENSE.txt file. 11 | */ 12 | /** \file */ 13 | 14 | #pragma once 15 | 16 | #include 17 | 18 | NAMESPACE_BEGIN(nanogui) 19 | 20 | /** 21 | * \class Popup popup.h nanogui/popup.h 22 | * 23 | * \brief Popup window for combo boxes, popup buttons, nested dialogs etc. 24 | * 25 | * Usually the Popup instance is constructed by another widget (e.g. \ref PopupButton) 26 | * and does not need to be created by hand. 27 | */ 28 | class NANOGUI_EXPORT Popup : public Window { 29 | public: 30 | enum Side { Left = 0, Right }; 31 | 32 | /// Create a new popup parented to a screen (first argument) and a parent window 33 | Popup(Widget *parent, Window *parentWindow); 34 | 35 | /// Return the anchor position in the parent window; the placement of the popup is relative to it 36 | void setAnchorPos(const Vector2i &anchorPos) { mAnchorPos = anchorPos; } 37 | /// Set the anchor position in the parent window; the placement of the popup is relative to it 38 | const Vector2i &anchorPos() const { return mAnchorPos; } 39 | 40 | /// Set the anchor height; this determines the vertical shift relative to the anchor position 41 | void setAnchorHeight(int anchorHeight) { mAnchorHeight = anchorHeight; } 42 | /// Return the anchor height; this determines the vertical shift relative to the anchor position 43 | int anchorHeight() const { return mAnchorHeight; } 44 | 45 | /// Set the side of the parent window at which popup will appear 46 | void setSide(Side popupSide) { mSide = popupSide; } 47 | /// Return the side of the parent window at which popup will appear 48 | Side side() const { return mSide; } 49 | 50 | /// Return the parent window of the popup 51 | Window *parentWindow() { return mParentWindow; } 52 | /// Return the parent window of the popup 53 | const Window *parentWindow() const { return mParentWindow; } 54 | 55 | /// Invoke the associated layout generator to properly place child widgets, if any 56 | virtual void performLayout(NVGcontext *ctx) override; 57 | 58 | /// Draw the popup window 59 | virtual void draw(NVGcontext* ctx) override; 60 | 61 | virtual void save(Serializer &s) const override; 62 | virtual bool load(Serializer &s) override; 63 | protected: 64 | /// Internal helper function to maintain nested window position values 65 | virtual void refreshRelativePlacement() override; 66 | 67 | protected: 68 | Window *mParentWindow; 69 | Vector2i mAnchorPos; 70 | int mAnchorHeight; 71 | Side mSide; 72 | public: 73 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 74 | }; 75 | 76 | NAMESPACE_END(nanogui) 77 | -------------------------------------------------------------------------------- /include/nanogui/popupbutton.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/popupbutton.h -- Button which launches a popup widget 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | NAMESPACE_BEGIN(nanogui) 20 | 21 | /** 22 | * \class PopupButton popupbutton.h nanogui/popupbutton.h 23 | * 24 | * \brief Button which launches a popup widget. 25 | * 26 | * \remark 27 | * This class overrides \ref nanogui::Widget::mIconExtraScale to be ``0.8f``, 28 | * which affects all subclasses of this Widget. Subclasses must explicitly 29 | * set a different value if needed (e.g., in their constructor). 30 | */ 31 | class NANOGUI_EXPORT PopupButton : public Button { 32 | public: 33 | PopupButton(Widget *parent, const std::string &caption = "Untitled", 34 | int buttonIcon = 0); 35 | virtual ~PopupButton(); 36 | 37 | void setChevronIcon(int icon) { mChevronIcon = icon; } 38 | int chevronIcon() const { return mChevronIcon; } 39 | 40 | void setSide(Popup::Side popupSide); 41 | Popup::Side side() const { return mPopup->side(); } 42 | 43 | Popup *popup() { return mPopup; } 44 | const Popup *popup() const { return mPopup; } 45 | 46 | virtual void draw(NVGcontext* ctx) override; 47 | virtual Vector2i preferredSize(NVGcontext *ctx) const override; 48 | virtual void performLayout(NVGcontext *ctx) override; 49 | 50 | virtual void save(Serializer &s) const override; 51 | virtual bool load(Serializer &s) override; 52 | protected: 53 | Popup *mPopup; 54 | int mChevronIcon; 55 | public: 56 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 57 | }; 58 | 59 | NAMESPACE_END(nanogui) 60 | -------------------------------------------------------------------------------- /include/nanogui/progressbar.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/progressbar.h -- Standard widget for visualizing progress 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | /** 20 | * \class ProgressBar progressbar.h nanogui/progressbar.h 21 | * 22 | * \brief Standard widget for visualizing progress. 23 | */ 24 | class NANOGUI_EXPORT ProgressBar : public Widget { 25 | public: 26 | ProgressBar(Widget *parent); 27 | 28 | float value() { return mValue; } 29 | void setValue(float value) { mValue = value; } 30 | 31 | virtual Vector2i preferredSize(NVGcontext *ctx) const override; 32 | virtual void draw(NVGcontext* ctx) override; 33 | 34 | virtual void save(Serializer &s) const override; 35 | virtual bool load(Serializer &s) override; 36 | protected: 37 | float mValue; 38 | public: 39 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 40 | }; 41 | 42 | NAMESPACE_END(nanogui) 43 | -------------------------------------------------------------------------------- /include/nanogui/python.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/python.h -- Macros to facilitate Python bindings of custom widgets 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | /// Provides a ``PYBIND11_OVERLOAD`` for any relevant Widget items that need to be bound. 19 | #define NANOGUI_WIDGET_OVERLOADS(Parent) \ 20 | bool mouseButtonEvent(const ::nanogui::Vector2i &p, int button, bool down, int modifiers) { \ 21 | PYBIND11_OVERLOAD(bool, Parent, mouseButtonEvent, p, button, down, modifiers); \ 22 | } \ 23 | bool mouseMotionEvent(const ::nanogui::Vector2i &p, const ::nanogui::Vector2i &rel, int button, int modifiers) { \ 24 | PYBIND11_OVERLOAD(bool, Parent, mouseMotionEvent, p, rel, button, modifiers); \ 25 | } \ 26 | bool mouseDragEvent(const ::nanogui::Vector2i &p, const ::nanogui::Vector2i &rel, int button, int modifiers) { \ 27 | PYBIND11_OVERLOAD(bool, Parent, mouseDragEvent, p, rel, button, modifiers); \ 28 | } \ 29 | bool mouseEnterEvent(const ::nanogui::Vector2i &p, bool enter) { \ 30 | PYBIND11_OVERLOAD(bool, Parent, mouseEnterEvent, p, enter); \ 31 | } \ 32 | bool scrollEvent(const ::nanogui::Vector2i &p, const ::nanogui::Vector2f &rel) { \ 33 | PYBIND11_OVERLOAD(bool, Parent, scrollEvent, p, rel); \ 34 | } \ 35 | bool focusEvent(bool focused) { \ 36 | PYBIND11_OVERLOAD(bool, Parent, focusEvent, focused); \ 37 | } \ 38 | bool keyboardEvent(int key, int scancode, int action, int modifiers) { \ 39 | PYBIND11_OVERLOAD(bool, Parent, keyboardEvent, key, scancode, action, modifiers); \ 40 | } \ 41 | bool keyboardCharacterEvent(unsigned int codepoint) { \ 42 | PYBIND11_OVERLOAD(bool, Parent, keyboardCharacterEvent, codepoint); \ 43 | } \ 44 | ::nanogui::Vector2i preferredSize(NVGcontext *ctx) const { \ 45 | PYBIND11_OVERLOAD(::nanogui::Vector2i, Parent, preferredSize, ctx); \ 46 | } \ 47 | void performLayout(NVGcontext *ctx) { \ 48 | PYBIND11_OVERLOAD(void, Parent, performLayout, ctx); \ 49 | } \ 50 | void draw(NVGcontext *ctx) { \ 51 | PYBIND11_OVERLOAD(void, Parent, draw, ctx); \ 52 | } 53 | 54 | /// Provides a ``PYBIND11_OVERLOAD`` for any relevant Layout items that need to be bound. 55 | #define NANOGUI_LAYOUT_OVERLOADS(Parent) \ 56 | ::nanogui::Vector2i preferredSize(NVGcontext *ctx, const ::nanogui::Widget *widget) const { \ 57 | PYBIND11_OVERLOAD(::nanogui::Vector2i, Parent, preferredSize, ctx, widget); \ 58 | } \ 59 | void performLayout(NVGcontext *ctx, ::nanogui::Widget *widget) const { \ 60 | PYBIND11_OVERLOAD(void, Parent, performLayout, ctx, widget); \ 61 | } 62 | 63 | /// Provides a ``PYBIND11_OVERLOAD`` for any relevant Screen items that need to be bound. 64 | #define NANOGUI_SCREEN_OVERLOADS(Parent) \ 65 | virtual void drawAll() { \ 66 | PYBIND11_OVERLOAD(void, Parent, drawAll); \ 67 | } \ 68 | virtual void drawContents() { \ 69 | PYBIND11_OVERLOAD(void, Parent, drawContents); \ 70 | } \ 71 | virtual bool dropEvent(const std::vector &filenames) { \ 72 | PYBIND11_OVERLOAD(bool, Parent, dropEvent, filenames); \ 73 | } \ 74 | virtual bool resizeEvent(const ::nanogui::Vector2i &size) { \ 75 | PYBIND11_OVERLOAD(bool, Parent, resizeEvent, size); \ 76 | } 77 | -------------------------------------------------------------------------------- /include/nanogui/serializer/opengl.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/serializer/opengl.h -- serialization support for OpenGL buffers 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | NAMESPACE_BEGIN(nanogui) 20 | NAMESPACE_BEGIN(detail) 21 | 22 | // bypass template specializations 23 | #ifndef DOXYGEN_SHOULD_SKIP_THIS 24 | 25 | template<> 26 | struct serialization_helper { 27 | static std::string type_id() { 28 | return "G"; 29 | } 30 | 31 | static void write(Serializer &s, const GLShader *value, size_t count) { 32 | for (size_t i = 0; i < count; ++i) { 33 | if (count > 1) 34 | s.push(value->name()); 35 | for (auto &item : value->mBufferObjects) { 36 | const GLShader::Buffer &buf = item.second; 37 | size_t totalSize = (size_t) buf.size * (size_t) buf.compSize; 38 | s.push(item.first); 39 | s.set("glType", buf.glType); 40 | s.set("compSize", buf.compSize); 41 | s.set("dim", buf.dim); 42 | s.set("size", buf.size); 43 | s.set("version", buf.version); 44 | Eigen::Matrix temp(1, totalSize); 45 | 46 | if (item.first == "indices") { 47 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf.id); 48 | glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, totalSize, 49 | temp.data()); 50 | } else { 51 | glBindBuffer(GL_ARRAY_BUFFER, buf.id); 52 | glGetBufferSubData(GL_ARRAY_BUFFER, 0, totalSize, temp.data()); 53 | } 54 | s.set("data", temp); 55 | s.pop(); 56 | } 57 | if (count > 1) 58 | s.pop(); 59 | ++value; 60 | } 61 | } 62 | 63 | static void read(Serializer &s, GLShader *value, size_t count) { 64 | for (size_t i = 0; i < count; ++i) { 65 | if (count > 1) 66 | s.push(value->name()); 67 | auto all_keys = s.keys(); 68 | 69 | std::set keys; 70 | for (auto key : all_keys) { 71 | auto it = key.find("."); 72 | if (it != std::string::npos) 73 | keys.insert(key.substr(0, it)); 74 | } 75 | value->bind(); 76 | for (auto key : keys) { 77 | if (value->mBufferObjects.find(key) == value->mBufferObjects.end()) { 78 | GLuint bufferID; 79 | glGenBuffers(1, &bufferID); 80 | value->mBufferObjects[key].id = bufferID; 81 | } 82 | GLShader::Buffer &buf = value->mBufferObjects[key]; 83 | Eigen::Matrix data; 84 | 85 | s.push(key); 86 | s.get("glType", buf.glType); 87 | s.get("compSize", buf.compSize); 88 | s.get("dim", buf.dim); 89 | s.get("size", buf.size); 90 | s.get("version", buf.version); 91 | s.get("data", data); 92 | s.pop(); 93 | 94 | size_t totalSize = (size_t) buf.size * (size_t) buf.compSize; 95 | if (key == "indices") { 96 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf.id); 97 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, totalSize, 98 | (void *) data.data(), GL_DYNAMIC_DRAW); 99 | } else { 100 | int attribID = value->attrib(key); 101 | glEnableVertexAttribArray(attribID); 102 | glBindBuffer(GL_ARRAY_BUFFER, buf.id); 103 | glBufferData(GL_ARRAY_BUFFER, totalSize, (void *) data.data(), 104 | GL_DYNAMIC_DRAW); 105 | glVertexAttribPointer(attribID, buf.dim, buf.glType, 106 | buf.compSize == 1 ? GL_TRUE : GL_FALSE, 0, 0); 107 | } 108 | } 109 | if (count > 1) 110 | s.pop(); 111 | ++value; 112 | } 113 | } 114 | }; 115 | 116 | #endif // DOXYGEN_SHOULD_SKIP_THIS 117 | 118 | NAMESPACE_END(detail) 119 | NAMESPACE_END(nanogui) 120 | -------------------------------------------------------------------------------- /include/nanogui/serializer/sparse.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/serializer/sparse.h -- serialization support for sparse matrices 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | NAMESPACE_BEGIN(nanogui) 19 | NAMESPACE_BEGIN(detail) 20 | 21 | // bypass template specializations 22 | #ifndef DOXYGEN_SHOULD_SKIP_THIS 23 | 24 | template 25 | struct serialization_helper> { 26 | typedef Eigen::SparseMatrix Matrix; 27 | typedef Eigen::Triplet Triplet; 28 | 29 | static std::string type_id() { 30 | return "S" + serialization_helper::type_id() + serialization_helper::type_id(); 31 | } 32 | 33 | static void write(Serializer &s, const Matrix *value, size_t count) { 34 | for (size_t i = 0; i < count; ++i) { 35 | size_t index = 0; 36 | std::vector> positions(value->nonZeros()); 37 | std::vector coeffs(value->nonZeros()); 38 | 39 | for (int k = 0; k < value->outerSize(); ++k) { 40 | for (typename Matrix::InnerIterator it(*value, k); it; ++it) { 41 | positions[index] = std::make_pair(it.row(), it.col()); 42 | coeffs[index] = it.value(); 43 | index++; 44 | } 45 | } 46 | 47 | Index rows = value->rows(), cols = value->cols(); 48 | s.write(&rows, sizeof(Index)); 49 | s.write(&cols, sizeof(Index)); 50 | serialization_helper>>::write(s, &positions, 1); 51 | serialization_helper>::write(s, &coeffs, 1); 52 | 53 | ++value; 54 | } 55 | } 56 | 57 | static void read(Serializer &s, Matrix *value, size_t count) { 58 | for (size_t i = 0; i < count; ++i) { 59 | Index rows, cols; 60 | s.read(&rows, sizeof(Index)); 61 | s.read(&cols, sizeof(Index)); 62 | 63 | std::vector> positions; 64 | std::vector coeffs; 65 | serialization_helper>>::read(s, &positions, 1); 66 | serialization_helper>::read(s, &coeffs, 1); 67 | 68 | if (coeffs.size() != positions.size()) 69 | throw std::runtime_error("Encountered corrupt data while unserializing sparse matrix!"); 70 | 71 | std::vector triplets(coeffs.size()); 72 | 73 | for (uint32_t i=0; iresize(rows, cols); 77 | value->setFromTriplets(triplets.begin(), triplets.end()); 78 | 79 | ++value; 80 | } 81 | } 82 | }; 83 | 84 | #endif // DOXYGEN_SHOULD_SKIP_THIS 85 | 86 | NAMESPACE_END(detail) 87 | NAMESPACE_END(nanogui) 88 | -------------------------------------------------------------------------------- /include/nanogui/slider.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/slider.h -- Fractional slider widget with mouse control 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | /** 20 | * \class Slider slider.h nanogui/slider.h 21 | * 22 | * \brief Fractional slider widget with mouse control. 23 | */ 24 | class NANOGUI_EXPORT Slider : public Widget { 25 | public: 26 | Slider(Widget *parent); 27 | 28 | float value() const { return mValue; } 29 | void setValue(float value) { mValue = value; } 30 | 31 | const Color &highlightColor() const { return mHighlightColor; } 32 | void setHighlightColor(const Color &highlightColor) { mHighlightColor = highlightColor; } 33 | 34 | std::pair range() const { return mRange; } 35 | void setRange(std::pair range) { mRange = range; } 36 | 37 | std::pair highlightedRange() const { return mHighlightedRange; } 38 | void setHighlightedRange(std::pair highlightedRange) { mHighlightedRange = highlightedRange; } 39 | 40 | std::function callback() const { return mCallback; } 41 | void setCallback(const std::function &callback) { mCallback = callback; } 42 | 43 | std::function finalCallback() const { return mFinalCallback; } 44 | void setFinalCallback(const std::function &callback) { mFinalCallback = callback; } 45 | 46 | virtual Vector2i preferredSize(NVGcontext *ctx) const override; 47 | virtual bool mouseDragEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override; 48 | virtual bool mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers) override; 49 | virtual void draw(NVGcontext* ctx) override; 50 | virtual void save(Serializer &s) const override; 51 | virtual bool load(Serializer &s) override; 52 | 53 | protected: 54 | float mValue; 55 | std::function mCallback; 56 | std::function mFinalCallback; 57 | std::pair mRange; 58 | std::pair mHighlightedRange; 59 | Color mHighlightColor; 60 | public: 61 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 62 | }; 63 | 64 | NAMESPACE_END(nanogui) 65 | -------------------------------------------------------------------------------- /include/nanogui/stackedwidget.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/stackedwidget.h -- Widget used to stack widgets on top 3 | of each other. Only the active widget is visible. 4 | 5 | The stacked widget was contributed by Stefan Ivanov. 6 | 7 | NanoGUI was developed by Wenzel Jakob . 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 | /** \file */ 15 | 16 | #pragma once 17 | 18 | #include 19 | 20 | NAMESPACE_BEGIN(nanogui) 21 | 22 | /** 23 | * \class StackedWidget stackedwidget.h nanogui/stackedwidget.h 24 | * 25 | * \brief A stack widget. 26 | */ 27 | class NANOGUI_EXPORT StackedWidget : public Widget { 28 | public: 29 | StackedWidget(Widget* parent); 30 | 31 | void setSelectedIndex(int index); 32 | int selectedIndex() const; 33 | 34 | virtual void performLayout(NVGcontext* ctx) override; 35 | virtual Vector2i preferredSize(NVGcontext* ctx) const override; 36 | virtual void addChild(int index, Widget* widget) override; 37 | 38 | private: 39 | int mSelectedIndex = -1; 40 | public: 41 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 42 | }; 43 | 44 | NAMESPACE_END(nanogui) 45 | -------------------------------------------------------------------------------- /include/nanogui/toolbutton.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/toolbutton.h -- Simple radio+toggle button with an icon 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | /** 20 | * \class ToolButton toolbutton.h nanogui/toolbutton.h 21 | * 22 | * \brief Simple radio+toggle button with an icon. 23 | */ 24 | class ToolButton : public Button { 25 | public: 26 | ToolButton(Widget *parent, int icon, 27 | const std::string &caption = "") 28 | : Button(parent, caption, icon) { 29 | setFlags(Flags::RadioButton | Flags::ToggleButton); 30 | setFixedSize(Vector2i(25, 25)); 31 | } 32 | public: 33 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 34 | }; 35 | 36 | NAMESPACE_END(nanogui) 37 | -------------------------------------------------------------------------------- /include/nanogui/vscrollpanel.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/vscrollpanel.h -- Adds a vertical scrollbar around a widget 3 | that is too big to fit into a certain area 4 | 5 | NanoGUI was developed by Wenzel Jakob . 6 | The widget drawing code is based on the NanoVG demo application 7 | by Mikko Mononen. 8 | 9 | All rights reserved. Use of this source code is governed by a 10 | BSD-style license that can be found in the LICENSE.txt file. 11 | */ 12 | /** \file */ 13 | 14 | #pragma once 15 | 16 | #include 17 | 18 | NAMESPACE_BEGIN(nanogui) 19 | 20 | /** 21 | * \class VScrollPanel vscrollpanel.h nanogui/vscrollpanel.h 22 | * 23 | * \brief Adds a vertical scrollbar around a widget that is too big to fit into 24 | * a certain area. 25 | */ 26 | class NANOGUI_EXPORT VScrollPanel : public Widget { 27 | public: 28 | VScrollPanel(Widget *parent); 29 | 30 | /// Return the current scroll amount as a value between 0 and 1. 0 means scrolled to the top and 1 to the bottom. 31 | float scroll() const { return mScroll; } 32 | /// Set the scroll amount to a value between 0 and 1. 0 means scrolled to the top and 1 to the bottom. 33 | void setScroll(float scroll) { mScroll = scroll; } 34 | 35 | virtual void performLayout(NVGcontext *ctx) override; 36 | virtual Vector2i preferredSize(NVGcontext *ctx) const override; 37 | virtual bool mouseDragEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override; 38 | virtual bool scrollEvent(const Vector2i &p, const Vector2f &rel) override; 39 | virtual void draw(NVGcontext *ctx) override; 40 | virtual void save(Serializer &s) const override; 41 | virtual bool load(Serializer &s) override; 42 | protected: 43 | int mChildPreferredHeight; 44 | float mScroll; 45 | bool mUpdateLayout; 46 | public: 47 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 48 | }; 49 | 50 | NAMESPACE_END(nanogui) 51 | -------------------------------------------------------------------------------- /include/nanogui/window.h: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/window.h -- Top-level window widget 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | /** \file */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | /** 20 | * \class Window window.h nanogui/window.h 21 | * 22 | * \brief Top-level window widget. 23 | */ 24 | class NANOGUI_EXPORT Window : public Widget { 25 | friend class Popup; 26 | public: 27 | Window(Widget *parent, const std::string &title = "Untitled"); 28 | 29 | /// Return the window title 30 | const std::string &title() const { return mTitle; } 31 | /// Set the window title 32 | void setTitle(const std::string &title) { mTitle = title; } 33 | 34 | /// Is this a model dialog? 35 | bool modal() const { return mModal; } 36 | /// Set whether or not this is a modal dialog 37 | void setModal(bool modal) { mModal = modal; } 38 | 39 | /// Return the panel used to house window buttons 40 | Widget *buttonPanel(); 41 | 42 | /// Dispose the window 43 | void dispose(); 44 | 45 | /// Center the window in the current \ref Screen 46 | void center(); 47 | 48 | /// Draw the window 49 | virtual void draw(NVGcontext *ctx) override; 50 | /// Handle window drag events 51 | virtual bool mouseDragEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override; 52 | /// Handle mouse events recursively and bring the current window to the top 53 | virtual bool mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers) override; 54 | /// Accept scroll events and propagate them to the widget under the mouse cursor 55 | virtual bool scrollEvent(const Vector2i &p, const Vector2f &rel) override; 56 | /// Compute the preferred size of the widget 57 | virtual Vector2i preferredSize(NVGcontext *ctx) const override; 58 | /// Invoke the associated layout generator to properly place child widgets, if any 59 | virtual void performLayout(NVGcontext *ctx) override; 60 | virtual void save(Serializer &s) const override; 61 | virtual bool load(Serializer &s) override; 62 | protected: 63 | /// Internal helper function to maintain nested window position values; overridden in \ref Popup 64 | virtual void refreshRelativePlacement(); 65 | protected: 66 | std::string mTitle; 67 | Widget *mButtonPanel; 68 | bool mModal; 69 | bool mDrag; 70 | public: 71 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 72 | }; 73 | 74 | NAMESPACE_END(nanogui) 75 | -------------------------------------------------------------------------------- /python/basics.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NANOGUI_PYTHON 2 | 3 | #include "python.h" 4 | 5 | DECLARE_WIDGET(Label); 6 | DECLARE_WIDGET(Popup); 7 | DECLARE_WIDGET(MessageDialog); 8 | DECLARE_WIDGET(VScrollPanel); 9 | DECLARE_WIDGET(ComboBox); 10 | DECLARE_WIDGET(ProgressBar); 11 | DECLARE_WIDGET(Slider); 12 | 13 | void register_basics(py::module &m) { 14 | py::class_, PyLabel>(m, "Label", D(Label)) 15 | .def(py::init(), 16 | py::arg("parent"), py::arg("caption"), py::arg("font") = std::string("sans"), 17 | py::arg("fontSize") = -1, 18 | D(Label, Label)) 19 | .def("caption", &Label::caption, D(Label, caption)) 20 | .def("setCaption", &Label::setCaption, D(Label, setCaption)) 21 | .def("font", &Label::font, D(Label, font)) 22 | .def("setFont", &Label::setFont, D(Label, setFont)) 23 | .def("color", &Label::color, D(Label, color)) 24 | .def("setColor", &Label::setColor, D(Label, setColor)); 25 | 26 | 27 | py::class_, PyPopup> popup(m, "Popup", D(Popup)); 28 | popup 29 | .def(py::init(), py::arg("parent"), py::arg("parentWindow"), D(Popup, Popup)) 30 | .def("anchorPos", &Popup::anchorPos, D(Popup, anchorPos)) 31 | .def("setAnchorPos", &Popup::setAnchorPos, D(Popup, setAnchorPos)) 32 | .def("anchorHeight", &Popup::anchorHeight, D(Popup, anchorHeight)) 33 | .def("setAnchorHeight", &Popup::setAnchorHeight, D(Popup, setAnchorHeight)) 34 | .def("parentWindow", (Window*(Popup::*)(void)) &Popup::parentWindow, D(Popup, parentWindow)) 35 | .def("side", &Popup::side, D(Popup, side)) 36 | .def("setSide", &Popup::setSide, D(Popup, setSide)); 37 | 38 | py::enum_(popup, "Side", D(Popup, Side)) 39 | .value("Left", Popup::Side::Left) 40 | .value("Right", Popup::Side::Right) 41 | .export_values(); 42 | 43 | py::class_, PyMessageDialog> mdlg(m, "MessageDialog", D(MessageDialog)); 44 | mdlg 45 | .def(py::init(), 47 | py::arg("parent"), py::arg("type"), py::arg("title") = std::string("Untitled"), 48 | py::arg("message") = std::string("Message"), py::arg("buttonText") = std::string("OK"), 49 | py::arg("altButtonText") = std::string("Cancel"), py::arg("altButton") = false, 50 | D(MessageDialog, MessageDialog)) 51 | .def("messageLabel", (Label * (MessageDialog::*)()) &MessageDialog::messageLabel, D(MessageDialog, messageLabel)) 52 | .def("callback", &MessageDialog::callback, D(MessageDialog, callback)) 53 | .def("setCallback", &MessageDialog::setCallback, D(MessageDialog, setCallback)); 54 | 55 | py::enum_(mdlg, "Type", D(MessageDialog, Type)) 56 | .value("Information", MessageDialog::Type::Information) 57 | .value("Question", MessageDialog::Type::Question) 58 | .value("Warning", MessageDialog::Type::Warning); 59 | 60 | py::class_, PyVScrollPanel>(m, "VScrollPanel", D(VScrollPanel)) 61 | .def(py::init(), py::arg("parent"), D(VScrollPanel, VScrollPanel)) 62 | .def("scroll", &VScrollPanel::scroll, D(VScrollPanel, scroll)) 63 | .def("setScroll", &VScrollPanel::setScroll, D(VScrollPanel, setScroll)); 64 | 65 | py::class_, PyComboBox>(m, "ComboBox", D(ComboBox)) 66 | .def(py::init(), py::arg("parent"), D(ComboBox, ComboBox)) 67 | .def(py::init &>(), 68 | py::arg("parent"), py::arg("items")/*, D(ComboBox, ComboBox, 2)*/) 69 | .def(py::init &, 70 | const std::vector &>(), 71 | py::arg("parent"), py::arg("items"), py::arg("itemsShort")/* ,D(ComboBox, ComboBox, 3)*/) 72 | .def("callback", &ComboBox::callback, D(ComboBox, callback)) 73 | .def("setCallback", &ComboBox::setCallback, D(ComboBox, setCallback)) 74 | .def("selectedIndex", &ComboBox::selectedIndex, D(ComboBox, selectedIndex)) 75 | .def("setSelectedIndex", &ComboBox::setSelectedIndex, D(ComboBox, setSelectedIndex)) 76 | .def("setItems", (void(ComboBox::*)(const std::vector&)) &ComboBox::setItems, D(ComboBox, setItems)) 77 | .def("setItems", (void(ComboBox::*)(const std::vector&, 78 | const std::vector&)) &ComboBox::setItems/*, D(ComboBox, setItems, 2)*/) 79 | .def("items", &ComboBox::items, D(ComboBox, items)) 80 | .def("itemsShort", &ComboBox::itemsShort, D(ComboBox, itemsShort)); 81 | 82 | py::class_, PyProgressBar>(m, "ProgressBar", D(ProgressBar)) 83 | .def(py::init(), py::arg("parent"), D(ProgressBar, ProgressBar)) 84 | .def("value", &ProgressBar::value, D(ProgressBar, value)) 85 | .def("setValue", &ProgressBar::setValue, D(ProgressBar, setValue)); 86 | 87 | py::class_, PySlider>(m, "Slider", D(Slider)) 88 | .def(py::init(), py::arg("parent"), D(Slider, Slider)) 89 | .def("value", &Slider::value, D(Slider, value)) 90 | .def("setValue", &Slider::setValue, D(Slider, setValue)) 91 | .def("highlightColor", &Slider::highlightColor, D(Slider, highlightColor)) 92 | .def("setHighlightColor", &Slider::setHighlightColor, D(Slider, setHighlightColor)) 93 | .def("range", &Slider::range, D(Slider, range)) 94 | .def("setRange", &Slider::setRange, D(Slider, setRange)) 95 | .def("highlightedRange", &Slider::highlightedRange, D(Slider, highlightedRange)) 96 | .def("setHighlightedRange", &Slider::setHighlightedRange, D(Slider, setHighlightedRange)) 97 | .def("setCallback", &Slider::setCallback, D(Slider, setCallback)) 98 | .def("callback", &Slider::callback, D(Slider, callback)) 99 | .def("setFinalCallback", &Slider::setFinalCallback, D(Slider, setFinalCallback)) 100 | .def("finalCallback", &Slider::finalCallback, D(Slider, finalCallback)); 101 | } 102 | #endif 103 | -------------------------------------------------------------------------------- /python/button.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NANOGUI_PYTHON 2 | 3 | #include "python.h" 4 | 5 | DECLARE_WIDGET(Button); 6 | DECLARE_WIDGET(ToolButton); 7 | DECLARE_WIDGET(PopupButton); 8 | DECLARE_WIDGET(CheckBox); 9 | 10 | void register_button(py::module &m) { 11 | py::class_, PyButton> button(m, "Button", D(Button)); 12 | button 13 | .def(py::init(), 14 | py::arg("parent"), py::arg("caption") = std::string("Untitled"), py::arg("icon") = 0, D(Button, Button)) 15 | .def("caption", &Button::caption, D(Button, caption)) 16 | .def("setCaption", &Button::setCaption, D(Button, setCaption)) 17 | .def("backgroundColor", &Button::backgroundColor, D(Button, backgroundColor)) 18 | .def("setBackgroundColor", &Button::setBackgroundColor, D(Button, setBackgroundColor)) 19 | .def("textColor", &Button::textColor, D(Button, textColor)) 20 | .def("setTextColor", &Button::setTextColor, D(Button, setTextColor)) 21 | .def("icon", &Button::icon, D(Button, icon)) 22 | .def("setIcon", &Button::setIcon, D(Button, setIcon)) 23 | .def("flags", &Button::flags, D(Button, flags)) 24 | .def("setFlags", &Button::setFlags, D(Button, setFlags)) 25 | .def("iconPosition", &Button::iconPosition, D(Button, iconPosition)) 26 | .def("setIconPosition", &Button::setIconPosition, D(Button, setIconPosition)) 27 | .def("pushed", &Button::pushed, D(Button, pushed)) 28 | .def("setPushed", &Button::setPushed, D(Button, setPushed)) 29 | .def("callback", &Button::callback, D(Button, callback)) 30 | .def("setCallback", &Button::setCallback, D(Button, setCallback)) 31 | .def("changeCallback", &Button::changeCallback, D(Button, changeCallback)) 32 | .def("setChangeCallback", &Button::setChangeCallback, D(Button, setChangeCallback)) 33 | .def("buttonGroup", &Button::buttonGroup, D(Button, buttonGroup)) 34 | .def("setButtonGroup", &Button::setButtonGroup, D(Button, setButtonGroup)); 35 | 36 | py::enum_(button, "IconPosition", D(Button, IconPosition)) 37 | .value("Left", Button::IconPosition::Left) 38 | .value("LeftCentered", Button::IconPosition::LeftCentered) 39 | .value("RightCentered", Button::IconPosition::RightCentered) 40 | .value("Right", Button::IconPosition::Right); 41 | 42 | py::enum_(button, "Flags", D(Button, Flags)) 43 | .value("NormalButton", Button::Flags::NormalButton) 44 | .value("RadioButton", Button::Flags::RadioButton) 45 | .value("ToggleButton", Button::Flags::ToggleButton) 46 | .value("PopupButton", Button::Flags::PopupButton); 47 | 48 | py::class_, PyToolButton>(m, "ToolButton", D(ToolButton)) 49 | .def(py::init(), 50 | py::arg("parent"), py::arg("icon"), py::arg("caption") = std::string(""), 51 | D(ToolButton, ToolButton)); 52 | 53 | py::class_, PyPopupButton> popupBtn(m, "PopupButton", D(PopupButton)); 54 | popupBtn 55 | .def(py::init(), 56 | py::arg("parent"), py::arg("caption") = std::string("Untitled"), 57 | py::arg("buttonIcon") = 0, D(PopupButton, PopupButton)) 58 | .def("popup", (Popup*(PopupButton::*)(void)) &PopupButton::popup, D(PopupButton, popup)) 59 | .def("chevronIcon", &PopupButton::chevronIcon, D(PopupButton, chevronIcon)) 60 | .def("setChevronIcon", &PopupButton::setChevronIcon, D(PopupButton, setChevronIcon)) 61 | .def("side", &PopupButton::side, D(PopupButton, side)) 62 | .def("setSide", &PopupButton::setSide, D(PopupButton, setSide)); 63 | 64 | py::class_, PyCheckBox>(m, "CheckBox", D(CheckBox)) 65 | .def(py::init(), py::arg("parent"), 66 | py::arg("caption") = std::string("Untitled"), 67 | D(CheckBox, CheckBox)) 68 | .def(py::init&>(), 69 | py::arg("parent"), py::arg("caption"), py::arg("callback"), 70 | D(CheckBox, CheckBox)) 71 | .def("caption", &CheckBox::caption, D(CheckBox, caption)) 72 | .def("setCaption", &CheckBox::setCaption, D(CheckBox, setCaption)) 73 | .def("checked", &CheckBox::checked, D(CheckBox, checked)) 74 | .def("setChecked", &CheckBox::setChecked, D(CheckBox, setChecked)) 75 | .def("pushed", &CheckBox::pushed, D(CheckBox, pushed)) 76 | .def("setPushed", &CheckBox::setPushed, D(CheckBox, setPushed)) 77 | .def("callback", &CheckBox::callback, D(CheckBox, callback)) 78 | .def("setCallback", &CheckBox::setCallback, D(CheckBox, setCallback)); 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /python/constants_glfw.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NANOGUI_PYTHON 2 | 3 | #include "python.h" 4 | 5 | void register_constants_glfw(py::module &m) { 6 | /* GLFW constants */ 7 | { 8 | #define C(name) g.attr(#name) = py::int_(GLFW_##name); 9 | py::module g = m.def_submodule("glfw"); 10 | C(KEY_UNKNOWN); C(KEY_SPACE); C(KEY_APOSTROPHE); C(KEY_COMMA); 11 | C(KEY_MINUS); C(KEY_PERIOD); C(KEY_SLASH); C(KEY_0); C(KEY_1); 12 | C(KEY_2); C(KEY_3); C(KEY_4); C(KEY_5); C(KEY_6); C(KEY_7); C(KEY_8); 13 | C(KEY_9); C(KEY_SEMICOLON); C(KEY_EQUAL); C(KEY_A); C(KEY_B); C(KEY_C); 14 | C(KEY_D); C(KEY_E); C(KEY_F); C(KEY_G); C(KEY_H); C(KEY_I); C(KEY_J); 15 | C(KEY_K); C(KEY_L); C(KEY_M); C(KEY_N); C(KEY_O); C(KEY_P); C(KEY_Q); 16 | C(KEY_R); C(KEY_S); C(KEY_T); C(KEY_U); C(KEY_V); C(KEY_W); C(KEY_X); 17 | C(KEY_Y); C(KEY_Z); C(KEY_LEFT_BRACKET); C(KEY_BACKSLASH); 18 | C(KEY_RIGHT_BRACKET); C(KEY_GRAVE_ACCENT); C(KEY_WORLD_1); 19 | C(KEY_WORLD_2); C(KEY_ESCAPE); C(KEY_ENTER); C(KEY_TAB); 20 | C(KEY_BACKSPACE); C(KEY_INSERT); C(KEY_DELETE); C(KEY_RIGHT); 21 | C(KEY_LEFT); C(KEY_DOWN); C(KEY_UP); C(KEY_PAGE_UP); C(KEY_PAGE_DOWN); 22 | C(KEY_HOME); C(KEY_END); C(KEY_CAPS_LOCK); C(KEY_SCROLL_LOCK); 23 | C(KEY_NUM_LOCK); C(KEY_PRINT_SCREEN); C(KEY_PAUSE); C(KEY_F1); 24 | C(KEY_F2); C(KEY_F3); C(KEY_F4); C(KEY_F5); C(KEY_F6); C(KEY_F7); 25 | C(KEY_F8); C(KEY_F9); C(KEY_F10); C(KEY_F11); C(KEY_F12); C(KEY_F13); 26 | C(KEY_F14); C(KEY_F15); C(KEY_F16); C(KEY_F17); C(KEY_F18); C(KEY_F19); 27 | C(KEY_F20); C(KEY_F21); C(KEY_F22); C(KEY_F23); C(KEY_F24); C(KEY_F25); 28 | C(KEY_KP_0); C(KEY_KP_1); C(KEY_KP_2); C(KEY_KP_3); C(KEY_KP_4); 29 | C(KEY_KP_5); C(KEY_KP_6); C(KEY_KP_7); C(KEY_KP_8); C(KEY_KP_9); 30 | C(KEY_KP_DECIMAL); C(KEY_KP_DIVIDE); C(KEY_KP_MULTIPLY); 31 | C(KEY_KP_SUBTRACT); C(KEY_KP_ADD); C(KEY_KP_ENTER); C(KEY_KP_EQUAL); 32 | C(KEY_LEFT_SHIFT); C(KEY_LEFT_CONTROL); C(KEY_LEFT_ALT); 33 | C(KEY_LEFT_SUPER); C(KEY_RIGHT_SHIFT); C(KEY_RIGHT_CONTROL); 34 | C(KEY_RIGHT_ALT); C(KEY_RIGHT_SUPER); C(KEY_MENU); C(KEY_LAST); 35 | C(MOD_SHIFT); C(MOD_CONTROL); C(MOD_ALT); C(MOD_SUPER); 36 | C(MOUSE_BUTTON_1); C(MOUSE_BUTTON_2); C(MOUSE_BUTTON_3); 37 | C(MOUSE_BUTTON_4); C(MOUSE_BUTTON_5); C(MOUSE_BUTTON_6); 38 | C(MOUSE_BUTTON_7); C(MOUSE_BUTTON_8); C(MOUSE_BUTTON_LAST); 39 | C(MOUSE_BUTTON_LEFT); C(MOUSE_BUTTON_RIGHT); C(MOUSE_BUTTON_MIDDLE); 40 | C(RELEASE); C(PRESS); C(REPEAT); 41 | #undef C 42 | } 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /python/eigen.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NANOGUI_PYTHON 2 | 3 | #include "python.h" 4 | 5 | void register_eigen(py::module &m) { 6 | py::class_(m, "Color", D(Color)) 7 | .def(py::init(), D(Color, Color, 7)) 8 | .def(py::init(), D(Color, Color, 5)) 9 | .def(py::init(), D(Color, Color, 7)) 10 | .def(py::init(), D(Color, Color, 5)) 11 | .def("contrastingColor", &Color::contrastingColor, 12 | D(Color, contrastingColor)) 13 | .def_property("r", [](const Color &c) { return c.r(); }, 14 | [](Color &c, float v) { c.r() = v; }, D(Color, r)) 15 | .def_property("g", [](const Color &c) { return c.g(); }, 16 | [](Color &c, float v) { c.g() = v; }, D(Color, g)) 17 | .def_property("b", [](const Color &c) { return c.b(); }, 18 | [](Color &c, float v) { c.b() = v; }, D(Color, b)) 19 | .def_property("w", [](const Color &c) { return c.w(); }, 20 | [](Color &c, float v) { c.w() = v; }, "Return a reference to the alpha channel.") 21 | .def("__repr__", [](const Color &c) { 22 | std::ostringstream oss; 23 | oss << c.transpose(); 24 | return oss.str(); 25 | }); 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /python/example2.py: -------------------------------------------------------------------------------- 1 | # python/example2.py -- Python version of an example application that shows 2 | # how to use the form helper class. For a C++ implementation, see 3 | # '../src/example2.cpp'. 4 | # 5 | # NanoGUI was developed by Wenzel Jakob . 6 | # The widget drawing code is based on the NanoVG demo application 7 | # by Mikko Mononen. 8 | # 9 | # All rights reserved. Use of this source code is governed by a 10 | # BSD-style license that can be found in the LICENSE.txt file. 11 | 12 | import nanogui 13 | import math 14 | import gc 15 | 16 | from nanogui import Screen, FormHelper 17 | 18 | bvar = True 19 | ivar = 12345678 20 | dvar = math.pi 21 | strvar = "A string" 22 | enumvar = 1 23 | colvar = nanogui.Color(.5, .5, .7, 1) 24 | 25 | 26 | def make_accessors(name): 27 | def setter(value): 28 | globals()[name] = value 29 | 30 | def getter(): 31 | return globals()[name] 32 | return setter, getter 33 | 34 | nanogui.init() 35 | 36 | use_gl_4_1 = False # Set to True to create an OpenGL 4.1 context. 37 | if use_gl_4_1: 38 | # NanoGUI presents many options for you to utilize at your discretion. 39 | # See include/nanogui/screen.h for what all of the options are. 40 | screen = Screen((500, 700), "NanoGUI test [GL 4.1]", glMajor=4, glMinor=1) 41 | else: 42 | screen = Screen((500, 700), "NanoGUI test") 43 | 44 | gui = FormHelper(screen) 45 | window = gui.addWindow((10, 10), "Form helper example") 46 | 47 | gui.addGroup("Basic types") 48 | gui.addBoolVariable("bool", *make_accessors("bvar")) 49 | gui.addStringVariable("string", *make_accessors("strvar")) 50 | 51 | gui.addGroup("Validating fields") 52 | gui.addIntVariable("int", *make_accessors("ivar")) 53 | gui.addDoubleVariable("double", *make_accessors("dvar")) 54 | 55 | gui.addGroup("Complex types") 56 | gui.addEnumVariable("Enumeration", *make_accessors("enumvar")) \ 57 | .setItems(["Item 1", "Item 2", "Item 3"]) 58 | 59 | def cp_final_cb(color): 60 | print( 61 | "ColorPicker Final Callback: [{0}, {1}, {2}, {3}]".format(color.r, 62 | color.g, 63 | color.b, 64 | color.w) 65 | ) 66 | 67 | 68 | gui.addColorVariable("Color", *make_accessors("colvar")).setFinalCallback(cp_final_cb) 69 | 70 | gui.addGroup("Other widgets") 71 | 72 | 73 | def cb(): 74 | print("Button pressed.") 75 | gui.addButton("A button", cb) 76 | 77 | screen.setVisible(True) 78 | screen.performLayout() 79 | window.center() 80 | 81 | nanogui.mainloop() 82 | screen = gui = window = None 83 | gc.collect() 84 | nanogui.shutdown() 85 | -------------------------------------------------------------------------------- /python/example3.py: -------------------------------------------------------------------------------- 1 | # python/example3.py -- running NanoGUI in detached mode 2 | # (contributed by Dmitriy Morozov) 3 | # 4 | # NanoGUI was developed by Wenzel Jakob . 5 | # The widget drawing code is based on the NanoVG demo application 6 | # by Mikko Mononen. 7 | # 8 | # All rights reserved. Use of this source code is governed by a 9 | # BSD-style license that can be found in the LICENSE.txt file. 10 | 11 | import nanogui 12 | from nanogui import * 13 | import time 14 | 15 | 16 | class TestApp(Screen): 17 | def __init__(self): 18 | super(TestApp, self).__init__((190, 170), "NanoGUI Test") 19 | 20 | window = Window(self, "Detached mode") 21 | window.setPosition((15, 15)) 22 | window.setLayout(GroupLayout()) 23 | 24 | Label(window, "Push buttons", "sans-bold") 25 | b = Button(window, "Plain button") 26 | 27 | def cb(): 28 | print("pushed!") 29 | b.setCallback(cb) 30 | 31 | b = Button(window, "Quit") 32 | 33 | def cb2(): 34 | self.setVisible(False) 35 | b.setCallback(cb2) 36 | 37 | self.performLayout() 38 | 39 | 40 | if __name__ == "__main__": 41 | nanogui.init() 42 | test = TestApp() 43 | test.drawAll() 44 | test.setVisible(True) 45 | 46 | print("Launching detached mainloop") 47 | h = nanogui.mainloop(detach=test) 48 | 49 | print("Back in Python context") 50 | for i in range(10): 51 | print(i) 52 | time.sleep(1) 53 | if not nanogui.active(): 54 | break 55 | 56 | h.join() 57 | nanogui.shutdown() 58 | -------------------------------------------------------------------------------- /python/example4.py: -------------------------------------------------------------------------------- 1 | # python/example4.py -- Python version of an example application that 2 | # shows how to use the GLCanvas widget. For a C++ implementation, see 3 | # '../src/example4.cpp'. 4 | # 5 | # NanoGUI was developed by Wenzel Jakob . 6 | # The widget drawing code is based on the NanoVG demo application 7 | # by Mikko Mononen. 8 | # 9 | # All rights reserved. Use of this source code is governed by a 10 | # BSD-style license that can be found in the LICENSE.txt file. 11 | 12 | import nanogui 13 | import random 14 | import math 15 | import time 16 | import gc 17 | 18 | from nanogui import Color, Screen, Window, GroupLayout, BoxLayout, \ 19 | ToolButton, Label, Button, Widget, \ 20 | PopupButton, CheckBox, MessageDialog, VScrollPanel, \ 21 | ImagePanel, ImageView, ComboBox, ProgressBar, Slider, \ 22 | TextBox, ColorWheel, Graph, GridLayout, \ 23 | Alignment, Orientation, TabWidget, IntBox, GLShader, GLCanvas 24 | 25 | from nanogui import gl, glfw, entypo 26 | 27 | 28 | class MyGLCanvas(GLCanvas): 29 | def __init__(self, parent): 30 | super(MyGLCanvas, self).__init__(parent) 31 | 32 | try: 33 | import numpy as np 34 | 35 | self.shader = GLShader() 36 | self.shader.init( 37 | # An identifying name 38 | "a_simple_shader", 39 | 40 | # Vertex shader 41 | """#version 330 42 | uniform mat4 modelViewProj; 43 | in vec3 position; 44 | in vec3 color; 45 | out vec4 frag_color; 46 | void main() { 47 | frag_color = 3.0 * modelViewProj * vec4(color, 1.0); 48 | gl_Position = modelViewProj * vec4(position, 1.0); 49 | }""", 50 | 51 | # Fragment shader 52 | """#version 330 53 | out vec4 color; 54 | in vec4 frag_color; 55 | void main() { 56 | color = frag_color; 57 | }""" 58 | ) 59 | 60 | # Draw a cube 61 | indices = np.array( 62 | [[0, 3, 3, 6, 7, 5, 4, 1, 4, 3, 5, 2], 63 | [1, 2, 2, 7, 6, 4, 5, 0, 0, 7, 6, 1], 64 | [3, 1, 6, 3, 5, 7, 1, 4, 3, 4, 2, 5]], 65 | dtype=np.int32) 66 | 67 | positions = np.array( 68 | [[-1, -1, 1, 1, -1, -1, 1, 1], 69 | [ 1, 1, 1, 1, -1, -1, -1, -1], 70 | [ 1, -1, -1, 1, 1, -1, -1, 1]], 71 | dtype=np.float32) 72 | 73 | colors = np.array( 74 | [[1, 0, 1, 0, 1, 0, 1, 0.5, 1, 1, 0.5, 0.5], 75 | [0, 1, 1, 0, 0, 1, 1, 0.5, 0, 0.5, 1, 1], 76 | [0, 0, 0, 1, 1, 1, 1, 0.5, 0.5, 0, 0, 0.5]], 77 | dtype=np.float32) 78 | 79 | self.shader.bind() 80 | self.shader.uploadIndices(indices) 81 | 82 | self.shader.uploadAttrib("position", positions) 83 | self.shader.uploadAttrib("color", colors) 84 | except ImportError: 85 | self.shader = None 86 | pass 87 | 88 | def drawGL(self): 89 | if self.shader is not None: 90 | import numpy as np 91 | self.shader.bind() 92 | 93 | current_time = time.time() 94 | angle_x = self.rotation[0] * current_time 95 | angle_y = self.rotation[1] * current_time 96 | angle_z = self.rotation[2] * current_time 97 | 98 | mvp_rotX = np.matrix( 99 | [[1, 0, 0, 0], 100 | [0, np.cos(angle_x), -np.sin(angle_x), 0], 101 | [0, np.sin(angle_x), np.cos(angle_x), 0], 102 | [0, 0, 0, 1]], 103 | dtype=np.float32) 104 | 105 | mvp_rotY = np.matrix( 106 | [[np.cos(angle_y), 0, np.sin(angle_y), 0], 107 | [0, 1, 0, 0], 108 | [-np.sin(angle_y), 0, np.cos(angle_y), 0], 109 | [0, 0, 0, 1]], 110 | dtype=np.float32) 111 | 112 | mvp_rotZ = np.matrix( 113 | [[np.cos(angle_z), -np.sin(angle_z), 0, 0], 114 | [np.sin(angle_z), np.cos(angle_z), 0, 0], 115 | [0, 0, 1, 0], 116 | [0, 0, 0, 1]], 117 | dtype=np.float32) 118 | 119 | mvp = mvp_rotX * mvp_rotY * mvp_rotZ 120 | 121 | mvp[0:3, 0:3] *= 0.25 122 | 123 | self.shader.setUniform("modelViewProj", mvp) 124 | 125 | gl.Enable(gl.DEPTH_TEST) 126 | self.shader.drawIndexed(gl.TRIANGLES, 0, 12) 127 | gl.Disable(gl.DEPTH_TEST) 128 | 129 | 130 | class TestApp(Screen): 131 | def __init__(self): 132 | super(TestApp, self).__init__((800, 600), "NanoGUI Test", False) 133 | 134 | window = Window(self, "GLCanvas Demo") 135 | window.setPosition((15, 15)) 136 | window.setLayout(GroupLayout()) 137 | 138 | self.canvas = MyGLCanvas(window) 139 | self.canvas.setBackgroundColor(Color(0.5, 0.5, 0.5, 1.0)) 140 | self.canvas.setSize((400, 400)) 141 | 142 | self.canvas.rotation = [0.25, 0.5, 0.33] 143 | 144 | tools = Widget(window) 145 | tools.setLayout(BoxLayout(Orientation.Horizontal, 146 | Alignment.Middle, 0, 5)) 147 | 148 | b0 = Button(tools, "Random Color") 149 | def cb0(): 150 | self.canvas.setBackgroundColor(Color(random.random(), random.random(), random.random(), 1.0)) 151 | b0.setCallback(cb0) 152 | 153 | b1 = Button(tools, "Random Rotation") 154 | def cb1(): 155 | self.canvas.rotation = [random.random(), random.random(), random.random()] 156 | b1.setCallback(cb1) 157 | 158 | self.performLayout() 159 | 160 | def keyboardEvent(self, key, scancode, action, modifiers): 161 | if super(TestApp, self).keyboardEvent(key, scancode, 162 | action, modifiers): 163 | return True 164 | if key == glfw.KEY_ESCAPE and action == glfw.PRESS: 165 | self.setVisible(False) 166 | return True 167 | return False 168 | 169 | if __name__ == "__main__": 170 | nanogui.init() 171 | test = TestApp() 172 | test.drawAll() 173 | test.setVisible(True) 174 | nanogui.mainloop() 175 | del test 176 | gc.collect() 177 | nanogui.shutdown() 178 | -------------------------------------------------------------------------------- /python/example_icons.py: -------------------------------------------------------------------------------- 1 | # python/example_icons.py -- Python version of an example application that shows 2 | # all available Entypo icons as they would appear in NanoGUI itself. For a C++ 3 | # implementation, see '../src/example_icons.cpp'. 4 | # 5 | # NanoGUI was developed by Wenzel Jakob . 6 | # The widget drawing code is based on the NanoVG demo application 7 | # by Mikko Mononen. 8 | # 9 | # All rights reserved. Use of this source code is governed by a 10 | # BSD-style license that can be found in the LICENSE.txt file. 11 | 12 | # Developer note: need to make a change to this file? 13 | # Please raise an Issue on GitHub describing what needs to change. This file 14 | # was generated, so the scripts that generated it needs to update as well. 15 | 16 | import gc 17 | 18 | import nanogui 19 | from nanogui import Screen, Window, Widget, GridLayout, VScrollPanel, Button 20 | from nanogui import entypo 21 | 22 | if __name__ == "__main__": 23 | nanogui.init() 24 | 25 | width = 1000 26 | half_width = width // 2 27 | height = 800 28 | 29 | # create a fixed size screen with one window 30 | screen = Screen((width, height), "NanoGUI Icons", False) 31 | window = Window(screen, "All Icons") 32 | window.setPosition((0, 0)) 33 | window.setFixedSize((width, height)) 34 | 35 | # attach a vertical scroll panel 36 | vscroll = VScrollPanel(window) 37 | vscroll.setFixedSize((width, height)) 38 | 39 | # vscroll should only have *ONE* child. this is what `wrapper` is for 40 | wrapper = Widget(vscroll) 41 | wrapper.setFixedSize((width, height)) 42 | wrapper.setLayout(GridLayout()) # defaults: 2 columns 43 | 44 | # NOTE: don't __dict__ crawl in real code! 45 | # this is just because it's more convenient to do this for enumerating all 46 | # of the icons -- see cpp example for alternative... 47 | for key in entypo.__dict__.keys(): 48 | if key.startswith("ICON_"): 49 | b = Button(wrapper, "entypo.{0}".format(key), entypo.__dict__[key]) 50 | b.setIconPosition(Button.IconPosition.Left) 51 | b.setFixedWidth(half_width) 52 | 53 | screen.performLayout() 54 | screen.drawAll() 55 | screen.setVisible(True) 56 | 57 | nanogui.mainloop() 58 | 59 | del screen 60 | gc.collect() 61 | 62 | nanogui.shutdown() 63 | -------------------------------------------------------------------------------- /python/formhelper.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NANOGUI_PYTHON 2 | 3 | #include "python.h" 4 | 5 | typedef IntBox Int64Box; 6 | 7 | void register_formhelper(py::module &m) { 8 | enum DummyEnum { }; 9 | 10 | py::class_(m, "FormHelper", D(FormHelper)) 11 | .def(py::init(), D(FormHelper, FormHelper)) 12 | .def("addWindow", &FormHelper::addWindow, py::arg("pos"), 13 | py::arg("title") = std::string("Untitled"), 14 | D(FormHelper, addWindow)) 15 | .def("addGroup", &FormHelper::addGroup, D(FormHelper, addGroup)) 16 | .def("addButton", &FormHelper::addButton, py::arg("label"), 17 | py::arg("cb"), D(FormHelper, addGroup)) 18 | .def("addBoolVariable", 19 | [](FormHelper &h, const std::string &label, 20 | const std::function &setter, 21 | const std::function &getter, bool editable) -> CheckBox* { 22 | return h.addVariable(label, setter, getter, editable); 23 | }, 24 | py::arg("label"), py::arg("setter"), py::arg("getter"), 25 | py::arg("editable") = true) 26 | .def("addIntVariable", 27 | [](FormHelper &h, const std::string &label, 28 | const std::function &setter, 29 | const std::function &getter, bool editable) -> Int64Box* { 30 | return h.addVariable(label, setter, getter, editable); 31 | }, 32 | py::arg("label"), py::arg("setter"), py::arg("getter"), 33 | py::arg("editable") = true) 34 | .def("addDoubleVariable", 35 | [](FormHelper &h, const std::string &label, 36 | const std::function &setter, 37 | const std::function &getter, bool editable) -> FloatBox* { 38 | return h.addVariable(label, setter, getter, editable); 39 | }, 40 | py::arg("label"), py::arg("setter"), py::arg("getter"), 41 | py::arg("editable") = true) 42 | .def("addStringVariable", 43 | [](FormHelper &h, const std::string &label, 44 | const std::function &setter, 45 | const std::function &getter, bool editable) -> TextBox* { 46 | return h.addVariable(label, setter, getter, editable); 47 | }, 48 | py::arg("label"), py::arg("setter"), py::arg("getter"), 49 | py::arg("editable") = true) 50 | .def("addColorVariable", 51 | [](FormHelper &h, const std::string &label, 52 | const std::function &setter, 53 | const std::function &getter, bool editable) -> ColorPicker* { 54 | return h.addVariable(label, setter, getter, editable); 55 | }, 56 | py::arg("label"), py::arg("setter"), py::arg("getter"), 57 | py::arg("editable") = true) 58 | .def("addEnumVariable", 59 | [](FormHelper &h, const std::string &label, 60 | const std::function &setter, 61 | const std::function &getter, bool editable) -> ComboBox* { 62 | return h.addVariable(label, 63 | reinterpret_cast&>(setter), 64 | reinterpret_cast&>(getter), 65 | editable); 66 | }, 67 | py::arg("label"), py::arg("setter"), py::arg("getter"), 68 | py::arg("editable") = true) 69 | .def("addWidget", &FormHelper::addWidget, D(FormHelper, addWidget)) 70 | .def("refresh", &FormHelper::refresh, D(FormHelper, refresh)) 71 | .def("window", &FormHelper::window, D(FormHelper, window)) 72 | .def("setWindow", &FormHelper::setWindow, D(FormHelper, setWindow)) 73 | .def("fixedSize", &FormHelper::fixedSize, D(FormHelper, fixedSize)) 74 | .def("setFixedSize", &FormHelper::setFixedSize, D(FormHelper, setFixedSize)) 75 | .def("groupFontName", &FormHelper::groupFontName, D(FormHelper, groupFontName)) 76 | .def("setGroupFontName", &FormHelper::setGroupFontName, D(FormHelper, setGroupFontName)) 77 | .def("labelFontName", &FormHelper::labelFontName, D(FormHelper, labelFontName)) 78 | .def("setLabelFontName", &FormHelper::setLabelFontName, D(FormHelper, setLabelFontName)) 79 | .def("groupFontSize", &FormHelper::groupFontSize, D(FormHelper, groupFontSize)) 80 | .def("setGroupFontSize", &FormHelper::setGroupFontSize, D(FormHelper, setGroupFontSize)) 81 | .def("labelFontSize", &FormHelper::labelFontSize, D(FormHelper, labelFontSize)) 82 | .def("setLabelFontSize", &FormHelper::setLabelFontSize, D(FormHelper, setLabelFontSize)) 83 | .def("widgetFontSize", &FormHelper::widgetFontSize, D(FormHelper, widgetFontSize)) 84 | .def("setWidgetFontSize", &FormHelper::setWidgetFontSize, D(FormHelper, setWidgetFontSize)); 85 | } 86 | #endif 87 | -------------------------------------------------------------------------------- /python/glcanvas.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NANOGUI_PYTHON 2 | 3 | #include "python.h" 4 | 5 | class PyGLCanvas : public GLCanvas { 6 | public: 7 | using GLCanvas::GLCanvas; 8 | NANOGUI_WIDGET_OVERLOADS(GLCanvas); 9 | 10 | void drawGL() { 11 | PYBIND11_OVERLOAD(void, GLCanvas, drawGL); 12 | } 13 | }; 14 | 15 | void register_glcanvas(py::module &m) { 16 | py::class_, PyGLCanvas> glcanvas(m, "GLCanvas", D(GLCanvas)); 17 | glcanvas 18 | .def(py::init(), py::arg("parent"), D(GLCanvas, GLCanvas)) 19 | .def("backgroundColor", &GLCanvas::backgroundColor, D(GLCanvas, backgroundColor)) 20 | .def("setBackgroundColor", &GLCanvas::setBackgroundColor, D(GLCanvas, setBackgroundColor)) 21 | .def("drawBorder", &GLCanvas::drawBorder, D(GLCanvas, drawBorder)) 22 | .def("setDrawBorder", &GLCanvas::setDrawBorder, D(GLCanvas, setDrawBorder)) 23 | .def("drawGL", &GLCanvas::drawGL, D(GLCanvas, drawGL)); 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /python/layout.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NANOGUI_PYTHON 2 | 3 | #include "python.h" 4 | 5 | DECLARE_LAYOUT(Layout); 6 | DECLARE_LAYOUT(GroupLayout); 7 | DECLARE_LAYOUT(BoxLayout); 8 | DECLARE_LAYOUT(GridLayout); 9 | DECLARE_LAYOUT(AdvancedGridLayout); 10 | 11 | void register_layout(py::module &m) { 12 | py::class_, PyLayout> layout(m, "Layout", D(Layout)); 13 | layout 14 | .def("preferredSize", &Layout::preferredSize, D(Layout, preferredSize)) 15 | .def("performLayout", &Layout::performLayout, D(Layout, performLayout)); 16 | 17 | py::class_, PyBoxLayout>(m, "BoxLayout", D(BoxLayout)) 18 | .def(py::init(), 19 | py::arg("orientation"), py::arg("alignment") = Alignment::Middle, 20 | py::arg("margin") = 0, py::arg("spacing") = 0, D(BoxLayout, BoxLayout)) 21 | .def("orientation", &BoxLayout::orientation, D(BoxLayout, orientation)) 22 | .def("setOrientation", &BoxLayout::setOrientation, D(BoxLayout, setOrientation)) 23 | .def("alignment", &BoxLayout::alignment, D(BoxLayout, alignment)) 24 | .def("setAlignment", &BoxLayout::setAlignment, D(BoxLayout, setAlignment)) 25 | .def("margin", &BoxLayout::margin, D(BoxLayout, margin)) 26 | .def("setMargin", &BoxLayout::setMargin, D(BoxLayout, setMargin)) 27 | .def("spacing", &BoxLayout::spacing, D(BoxLayout, spacing)) 28 | .def("setSpacing", &BoxLayout::setSpacing, D(BoxLayout, setSpacing)); 29 | 30 | py::class_, PyGroupLayout>(m, "GroupLayout", D(GroupLayout)) 31 | .def(py::init(), 32 | py::arg("margin") = 15, py::arg("spacing") = 6, 33 | py::arg("groupSpacing") = 14, py::arg("groupIndent") = 20, 34 | D(GroupLayout, GroupLayout)) 35 | .def("margin", &GroupLayout::margin, D(GroupLayout, margin)) 36 | .def("setMargin", &GroupLayout::setMargin, D(GroupLayout, setMargin)) 37 | .def("spacing", &GroupLayout::spacing, D(GroupLayout, spacing)) 38 | .def("setSpacing", &GroupLayout::setSpacing, D(GroupLayout, setSpacing)) 39 | .def("groupIndent", &GroupLayout::groupIndent, D(GroupLayout, groupIndent)) 40 | .def("setGroupIndent", &GroupLayout::setGroupIndent, D(GroupLayout, setGroupIndent)) 41 | .def("groupSpacing", &GroupLayout::groupSpacing, D(GroupLayout, groupSpacing)) 42 | .def("setGroupSpacing", &GroupLayout::setGroupSpacing, D(GroupLayout, setGroupSpacing)); 43 | 44 | py::class_, PyGridLayout>(m, "GridLayout", D(GridLayout)) 45 | .def(py::init(), 46 | py::arg("orientation") = Orientation::Horizontal, 47 | py::arg("resolution") = 2, py::arg("alignment") = Alignment::Middle, 48 | py::arg("margin") = 0, py::arg("spacing") = 0, 49 | D(GridLayout, GridLayout)) 50 | .def("orientation", &GridLayout::orientation, D(GridLayout, orientation)) 51 | .def("setOrientation", &GridLayout::setOrientation, D(GridLayout, setOrientation)) 52 | .def("resolution", &GridLayout::resolution, D(GridLayout, resolution)) 53 | .def("setResolution", &GridLayout::setResolution, D(GridLayout, setResolution)) 54 | .def("margin", &GridLayout::margin, D(GridLayout, margin)) 55 | .def("setMargin", &GridLayout::setMargin, D(GridLayout, setMargin)) 56 | .def("spacing", &GridLayout::spacing, D(GridLayout, spacing)) 57 | .def("setSpacing", (void(GridLayout::*)(int)) &GridLayout::setSpacing, D(GridLayout, setSpacing)) 58 | .def("setSpacing", (void(GridLayout::*)(int, int)) &GridLayout::setSpacing, D(GridLayout, setSpacing, 2)) 59 | .def("alignment", &GridLayout::alignment, D(GridLayout, alignment)) 60 | .def("setColAlignment", (void(GridLayout::*)(Alignment)) &GridLayout::setColAlignment, D(GridLayout, setColAlignment)) 61 | .def("setRowAlignment", (void(GridLayout::*)(Alignment)) &GridLayout::setRowAlignment, D(GridLayout, setRowAlignment)) 62 | .def("setColAlignment", (void(GridLayout::*)(const std::vector&)) &GridLayout::setColAlignment/*, D(GridLayout, setColAlignment, 2)*/) 63 | .def("setRowAlignment", (void(GridLayout::*)(const std::vector&)) &GridLayout::setRowAlignment/*, D(GridLayout, setRowAlignment, 2)*/); 64 | 65 | py::class_, PyAdvancedGridLayout> advGridLayout( 66 | m, "AdvancedGridLayout", D(AdvancedGridLayout)); 67 | 68 | advGridLayout 69 | .def(py::init &, const std::vector &>(), 70 | py::arg("widths"), py::arg("heights"), 71 | D(AdvancedGridLayout, AdvancedGridLayout)) 72 | .def("rowCount", &AdvancedGridLayout::rowCount, D(AdvancedGridLayout, rowCount)) 73 | .def("colCount", &AdvancedGridLayout::colCount, D(AdvancedGridLayout, colCount)) 74 | .def("margin", &AdvancedGridLayout::margin, D(AdvancedGridLayout, margin)) 75 | .def("setMargin", &AdvancedGridLayout::setMargin, D(AdvancedGridLayout, setMargin)) 76 | .def("appendRow", &AdvancedGridLayout::appendRow, py::arg("size"), 77 | py::arg("stretch") = 0, D(AdvancedGridLayout, appendRow)) 78 | .def("appendCol", &AdvancedGridLayout::appendCol, py::arg("size"), 79 | py::arg("stretch") = 0, D(AdvancedGridLayout, appendCol)) 80 | .def("setRowStretch", &AdvancedGridLayout::setRowStretch, D(AdvancedGridLayout, setRowStretch)) 81 | .def("setColStretch", &AdvancedGridLayout::setColStretch, D(AdvancedGridLayout, setColStretch)) 82 | .def("setAnchor", &AdvancedGridLayout::setAnchor, D(AdvancedGridLayout, setAnchor)) 83 | .def("anchor", &AdvancedGridLayout::anchor, D(AdvancedGridLayout, anchor)); 84 | 85 | py::class_(advGridLayout, "Anchor") 86 | .def(py::init(), 87 | py::arg("x"), py::arg("y"), 88 | py::arg("horiz") = Alignment::Fill, 89 | py::arg("vert") = Alignment::Fill, 90 | D(AdvancedGridLayout, Anchor, Anchor, 2)) 91 | .def(py::init(), 92 | py::arg("x"), py::arg("y"), py::arg("w"), py::arg("h"), 93 | py::arg("horiz") = Alignment::Fill, 94 | py::arg("vert") = Alignment::Fill, 95 | D(AdvancedGridLayout, Anchor, Anchor, 3)); 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /python/misc.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NANOGUI_PYTHON 2 | 3 | #include "python.h" 4 | 5 | DECLARE_WIDGET(ColorWheel); 6 | DECLARE_WIDGET(ColorPicker); 7 | DECLARE_WIDGET(Graph); 8 | DECLARE_WIDGET(ImageView); 9 | DECLARE_WIDGET(ImagePanel); 10 | 11 | void register_misc(py::module &m) { 12 | py::class_, PyColorWheel>(m, "ColorWheel", D(ColorWheel)) 13 | .def(py::init(), py::arg("parent"), D(ColorWheel, ColorWheel)) 14 | .def(py::init(), py::arg("parent"), py::arg("Color")) 15 | .def("color", &ColorWheel::color, D(ColorWheel, color)) 16 | .def("setColor", &ColorWheel::setColor, D(ColorWheel, setColor)) 17 | .def("callback", &ColorWheel::callback, D(ColorWheel, callback)) 18 | .def("setCallback", &ColorWheel::setCallback, D(ColorWheel, setCallback)); 19 | 20 | py::class_, PyColorPicker>(m, "ColorPicker", D(ColorPicker)) 21 | .def(py::init(), py::arg("parent"), D(ColorPicker, ColorPicker)) 22 | .def(py::init(), py::arg("parent"), py::arg("Color")) 23 | .def("color", &ColorPicker::color, D(ColorPicker, color)) 24 | .def("setColor", &ColorPicker::setColor, D(ColorPicker, setColor)) 25 | .def("callback", &ColorPicker::callback, D(ColorPicker, callback)) 26 | .def("setCallback", &ColorPicker::setCallback, D(ColorPicker, setCallback)) 27 | .def("finalCallback", &ColorPicker::finalCallback, D(ColorPicker, finalCallback)) 28 | .def("setFinalCallback", &ColorPicker::setFinalCallback, D(ColorPicker, setFinalCallback)); 29 | 30 | py::class_, PyGraph>(m, "Graph", D(Graph)) 31 | .def(py::init(), py::arg("parent"), 32 | py::arg("caption") = std::string("Untitled"), D(Graph, Graph)) 33 | .def("caption", &Graph::caption, D(Graph, caption)) 34 | .def("setCaption", &Graph::setCaption, D(Graph, setCaption)) 35 | .def("header", &Graph::header, D(Graph, header)) 36 | .def("setHeader", &Graph::setHeader, D(Graph, setHeader)) 37 | .def("footer", &Graph::footer, D(Graph, footer)) 38 | .def("setFooter", &Graph::setFooter, D(Graph, setFooter)) 39 | .def("backgroundColor", &Graph::backgroundColor, D(Graph, backgroundColor)) 40 | .def("setBackgroundColor", &Graph::setBackgroundColor, D(Graph, setBackgroundColor)) 41 | .def("foregroundColor", &Graph::foregroundColor, D(Graph, foregroundColor)) 42 | .def("setForegroundColor", &Graph::setForegroundColor, D(Graph, setForegroundColor)) 43 | .def("textColor", &Graph::textColor, D(Graph, textColor)) 44 | .def("setTextColor", &Graph::setTextColor, D(Graph, setTextColor)) 45 | .def("values", (VectorXf &(Graph::*)(void)) &Graph::values, D(Graph, values)) 46 | .def("setValues", &Graph::setValues, D(Graph, setValues)); 47 | 48 | py::class_, PyImageView>(m, "ImageView", D(ImageView)) 49 | .def(py::init(), D(ImageView, ImageView)) 50 | .def("bindImage", &ImageView::bindImage, D(ImageView, bindImage)) 51 | .def("imageShader", &ImageView::imageShader, D(ImageView, imageShader)) 52 | .def("scaledImageSize", &ImageView::scaledImageSize, D(ImageView, scaledImageSize)) 53 | .def("offset", &ImageView::offset, D(ImageView, offset)) 54 | .def("setOffset", &ImageView::setOffset, D(ImageView, setOffset)) 55 | .def("scale", &ImageView::scale, D(ImageView, scale)) 56 | .def("fixedOffset", &ImageView::fixedOffset, D(ImageView, fixedOffset)) 57 | .def("setFixedOffset", &ImageView::setFixedOffset, D(ImageView, setFixedOffset)) 58 | .def("fixedScale", &ImageView::fixedScale, D(ImageView, fixedScale)) 59 | .def("setFixedScale", &ImageView::setFixedScale, D(ImageView, setFixedScale)) 60 | .def("zoomSensitivity", &ImageView::zoomSensitivity, D(ImageView, zoomSensitivity)) 61 | .def("setZoomSensitivity", &ImageView::setZoomSensitivity, D(ImageView, setZoomSensitivity)) 62 | .def("gridThreshold", &ImageView::gridThreshold, D(ImageView, gridThreshold)) 63 | .def("setGridThreshold", &ImageView::setGridThreshold, D(ImageView, setGridThreshold)) 64 | .def("pixelInfoThreshold", &ImageView::pixelInfoThreshold, D(ImageView, pixelInfoThreshold)) 65 | .def("setPixelInfoThreshold", &ImageView::setPixelInfoThreshold, D(ImageView, setPixelInfoThreshold)) 66 | .def("setPixelInfoCallback", &ImageView::setPixelInfoCallback, D(ImageView, setPixelInfoCallback)) 67 | .def("pixelInfoCallback", &ImageView::pixelInfoCallback, D(ImageView, pixelInfoCallback)) 68 | .def("setFontScaleFactor", &ImageView::setFontScaleFactor, D(ImageView, setFontScaleFactor)) 69 | .def("fontScaleFactor", &ImageView::fontScaleFactor, D(ImageView, fontScaleFactor)) 70 | .def("imageCoordinateAt", &ImageView::imageCoordinateAt, D(ImageView, imageCoordinateAt)) 71 | .def("clampedImageCoordinateAt", &ImageView::clampedImageCoordinateAt, D(ImageView, clampedImageCoordinateAt)) 72 | .def("positionForCoordinate", &ImageView::positionForCoordinate, D(ImageView, positionForCoordinate)) 73 | .def("setImageCoordinateAt", &ImageView::setImageCoordinateAt, D(ImageView, setImageCoordinateAt)) 74 | .def("center",&ImageView::center, D(ImageView, center)) 75 | .def("fit", &ImageView::fit, D(ImageView, fit)) 76 | .def("setScaleCentered", &ImageView::setScaleCentered, D(ImageView, setScaleCentered)) 77 | .def("moveOffset", &ImageView::moveOffset, D(ImageView, moveOffset)) 78 | .def("zoom", &ImageView::zoom, D(ImageView, zoom)) 79 | .def("gridVisible", &ImageView::gridVisible, D(ImageView, gridVisible)) 80 | .def("pixelInfoVisible", &ImageView::pixelInfoVisible, D(ImageView, pixelInfoVisible)) 81 | .def("helpersVisible", &ImageView::helpersVisible, D(ImageView, helpersVisible)); 82 | 83 | py::class_, PyImagePanel>(m, "ImagePanel", D(ImagePanel)) 84 | .def(py::init(), py::arg("parent"), D(ImagePanel, ImagePanel)) 85 | .def("images", &ImagePanel::images, D(ImagePanel, images)) 86 | .def("setImages", &ImagePanel::setImages, D(ImagePanel, setImages)) 87 | .def("callback", &ImagePanel::callback, D(ImagePanel, callback)) 88 | .def("setCallback", &ImagePanel::setCallback, D(ImagePanel, setCallback)); 89 | } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /python/python.h: -------------------------------------------------------------------------------- 1 | #if !defined(__PYTHON_H) 2 | #define __PYTHON_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "py_doc.h" 13 | 14 | PYBIND11_MAKE_OPAQUE(nanogui::Color) 15 | 16 | #define D(...) DOC(nanogui, __VA_ARGS__ ) 17 | 18 | #define DECLARE_LAYOUT(Name) \ 19 | class Py##Name : public Name { \ 20 | public: \ 21 | using Name::Name; \ 22 | NANOGUI_LAYOUT_OVERLOADS(Name); \ 23 | } 24 | 25 | #define DECLARE_WIDGET(Name) \ 26 | class Py##Name : public Name { \ 27 | public: \ 28 | using Name::Name; \ 29 | NANOGUI_WIDGET_OVERLOADS(Name); \ 30 | } 31 | 32 | #define DECLARE_SCREEN(Name) \ 33 | class Py##Name : public Name { \ 34 | public: \ 35 | using Name::Name; \ 36 | NANOGUI_WIDGET_OVERLOADS(Name); \ 37 | NANOGUI_SCREEN_OVERLOADS(Name); \ 38 | } 39 | 40 | namespace py = pybind11; 41 | using namespace nanogui; 42 | 43 | /// Make pybind aware of the ref-counted wrapper type 44 | PYBIND11_DECLARE_HOLDER_TYPE(T, ref); 45 | 46 | #endif /* __PYTHON_H */ 47 | 48 | -------------------------------------------------------------------------------- /python/tabs.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NANOGUI_PYTHON 2 | 3 | #include "python.h" 4 | 5 | DECLARE_WIDGET(StackedWidget); 6 | DECLARE_WIDGET(TabHeader); 7 | DECLARE_WIDGET(TabWidget); 8 | 9 | void register_tabs(py::module &m) { 10 | py::class_, PyStackedWidget>(m, "StackedWidget", D(StackedWidget)) 11 | .def(py::init(), D(StackedWidget, StackedWidget)) 12 | .def("selectedIndex", &StackedWidget::selectedIndex, D(StackedWidget, selectedIndex)) 13 | .def("setSelectedIndex", &StackedWidget::setSelectedIndex, D(StackedWidget, setSelectedIndex)); 14 | 15 | py::class_, PyTabHeader>(m, "TabHeader", D(TabHeader)) 16 | .def(py::init(), D(TabHeader, TabHeader)) 17 | .def("setFont", &TabHeader::setFont, D(TabHeader, setFont)) 18 | .def("font", &TabHeader::font, D(TabHeader, font)) 19 | .def("overflowing", &TabHeader::overflowing, D(TabHeader, overflowing)) 20 | .def("callback", &TabHeader::callback, D(TabHeader, callback)) 21 | .def("setCallback", &TabHeader::setCallback, D(TabHeader, setCallback)) 22 | .def("activeTab", &TabHeader::activeTab, D(TabHeader, activeTab)) 23 | .def("setActiveTab", &TabHeader::setActiveTab, D(TabHeader, setActiveTab)) 24 | .def("addTab", (void (TabHeader::*)(const std::string &)) &TabHeader::addTab, D(TabHeader, addTab)) 25 | .def("addTab", (void (TabHeader::*)(int index, const std::string &)) &TabHeader::addTab, D(TabHeader, addTab, 2)) 26 | .def("removeTab", (int (TabHeader::*)(const std::string &)) &TabHeader::removeTab, D(TabHeader, removeTab)) 27 | .def("removeTab", (void (TabHeader::*)(int index)) &TabHeader::removeTab, D(TabHeader, removeTab, 2)) 28 | .def("tabLabelAt", &TabHeader::tabLabelAt, D(TabHeader, tabLabelAt)) 29 | .def("tabIndex", &TabHeader::tabIndex, D(TabHeader, tabIndex)) 30 | .def("ensureTabVisible", &TabHeader::ensureTabVisible, D(TabHeader, ensureTabVisible)); 31 | 32 | py::class_, PyTabWidget>(m, "TabWidget", D(TabWidget)) 33 | .def(py::init(), D(TabWidget, TabWidget)) 34 | .def("setActiveTab", &TabWidget::setActiveTab, D(TabWidget, setActiveTab)) 35 | .def("activeTab", &TabWidget::activeTab, D(TabWidget, activeTab)) 36 | .def("tabCount", &TabWidget::tabCount, D(TabWidget, tabCount)) 37 | .def("setCallback", &TabWidget::setCallback, D(TabWidget, setCallback)) 38 | .def("callback", &TabWidget::callback, D(TabWidget, callback)) 39 | .def("addTab", (void (TabWidget::*)(const std::string &, Widget *)) &TabWidget::addTab, D(TabWidget, addTab)) 40 | .def("addTab", (void (TabWidget::*)(int index, const std::string &, Widget *)) &TabWidget::addTab, D(TabWidget, addTab, 2)) 41 | .def("createTab", (Widget *(TabWidget::*)(const std::string &)) &TabWidget::createTab, D(TabWidget, createTab)) 42 | .def("createTab", (Widget *(TabWidget::*)(int index, const std::string &)) &TabWidget::createTab, D(TabWidget, createTab, 2)) 43 | .def("removeTab", (bool (TabWidget::*)(const std::string &)) &TabWidget::removeTab, D(TabWidget, removeTab)) 44 | .def("removeTab", (void (TabWidget::*)(int index)) &TabWidget::removeTab, D(TabWidget, removeTab, 2)) 45 | .def("tabLabelAt", &TabWidget::tabLabelAt, D(TabWidget, tabLabelAt)) 46 | .def("tabIndex", &TabWidget::tabIndex, D(TabWidget, tabIndex)) 47 | .def("tab", (Widget * (TabWidget::*)(const std::string &)) &TabWidget::tab, D(TabWidget, tab)) 48 | .def("tab", (Widget * (TabWidget::*)(int)) &TabWidget::tab, D(TabWidget, tab)) 49 | .def("ensureTabVisible", &TabWidget::ensureTabVisible, D(TabWidget, ensureTabVisible)); 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /python/textbox.cpp: -------------------------------------------------------------------------------- 1 | #ifdef NANOGUI_PYTHON 2 | 3 | #include "python.h" 4 | 5 | typedef FloatBox DoubleBox; 6 | typedef IntBox Int64Box; 7 | 8 | DECLARE_WIDGET(TextBox); 9 | DECLARE_WIDGET(DoubleBox); 10 | DECLARE_WIDGET(Int64Box); 11 | 12 | void register_textbox(py::module &m) { 13 | py::class_, PyTextBox> tbox(m, "TextBox", D(TextBox)); 14 | tbox 15 | .def(py::init(), py::arg("parent"), 16 | py::arg("value") = std::string("Untitled"), D(TextBox, TextBox)) 17 | .def("editable", &TextBox::editable, D(TextBox, editable)) 18 | .def("setEditable", &TextBox::setEditable, D(TextBox, setEditable)) 19 | .def("spinnable", &TextBox::spinnable, D(TextBox, spinnable)) 20 | .def("setSpinnable", &TextBox::setSpinnable, D(TextBox, setSpinnable)) 21 | .def("value", &TextBox::value, D(TextBox, value)) 22 | .def("setValue", &TextBox::setValue, D(TextBox, setValue)) 23 | .def("defaultValue", &TextBox::defaultValue, D(TextBox, defaultValue)) 24 | .def("setDefaultValue", &TextBox::setDefaultValue, D(TextBox, setDefaultValue)) 25 | .def("alignment", &TextBox::alignment, D(TextBox, alignment)) 26 | .def("setAlignment", &TextBox::setAlignment, D(TextBox, setAlignment)) 27 | .def("units", &TextBox::units, D(TextBox, units)) 28 | .def("setUnits", &TextBox::setUnits, D(TextBox, setUnits)) 29 | .def("unitsImage", &TextBox::unitsImage, D(TextBox, unitsImage)) 30 | .def("setUnitsImage", &TextBox::setUnitsImage, D(TextBox, setUnitsImage)) 31 | .def("format", &TextBox::format, D(TextBox, format)) 32 | .def("setFormat", &TextBox::setFormat, D(TextBox, setFormat)) 33 | .def("placeholder", &TextBox::placeholder, D(TextBox, placeholder)) 34 | .def("setPlaceholder", &TextBox::setPlaceholder, D(TextBox, setPlaceholder)) 35 | .def("callback", &TextBox::callback, D(TextBox, callback)) 36 | .def("setCallback", &TextBox::setCallback, D(TextBox, setCallback)); 37 | 38 | py::enum_(tbox, "Alignment", D(TextBox, Alignment)) 39 | .value("Left", TextBox::Alignment::Left) 40 | .value("Center", TextBox::Alignment::Center) 41 | .value("Right", TextBox::Alignment::Right); 42 | 43 | py::class_, PyInt64Box>(m, "IntBox", D(IntBox)) 44 | .def(py::init(), py::arg("parent"), py::arg("value") = (int64_t) 0, D(IntBox, IntBox)) 45 | .def("value", &Int64Box::value, D(IntBox, value)) 46 | .def("setValue", (void (Int64Box::*)(int64_t)) &Int64Box::setValue, D(IntBox, setValue)) 47 | .def("setCallback", (void (Int64Box::*)(const std::function&)) 48 | &Int64Box::setCallback, D(IntBox, setCallback)) 49 | .def("setValueIncrement", &Int64Box::setValueIncrement, D(IntBox, setValueIncrement)) 50 | .def("setMinValue", &Int64Box::setMinValue, D(IntBox, setMinValue)) 51 | .def("setMaxValue", &Int64Box::setMaxValue, D(IntBox, setMaxValue)) 52 | .def("setMinValue", &Int64Box::setMinMaxValues, D(IntBox, setMinMaxValues)); 53 | 54 | py::class_, PyDoubleBox>(m, "FloatBox", D(FloatBox)) 55 | .def(py::init(), py::arg("parent"), py::arg("value") = 0.0) 56 | .def("value", &DoubleBox::value, D(FloatBox, value)) 57 | .def("setValue", (void (DoubleBox::*)(double)) &DoubleBox::setValue, D(FloatBox, setValue)) 58 | .def("setCallback", (void (DoubleBox::*)(const std::function&)) 59 | &DoubleBox::setCallback, D(FloatBox, setCallback)) 60 | .def("setValueIncrement", &DoubleBox::setValueIncrement, D(FloatBox, setValueIncrement)) 61 | .def("setMinValue", &DoubleBox::setMinValue, D(FloatBox, setMinValue)) 62 | .def("setMaxValue", &DoubleBox::setMaxValue, D(FloatBox, setMaxValue)) 63 | .def("setMinValue", &DoubleBox::setMinMaxValues, D(FloatBox, setMinMaxValues)); 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /python/theme.cpp: -------------------------------------------------------------------------------- 1 | #include "python.h" 2 | 3 | class PyTheme : public Theme { 4 | public: 5 | using Theme::Theme; 6 | }; 7 | 8 | void register_theme(py::module &m) { 9 | py::class_, PyTheme> theme(m, "Theme", D(Theme)); 10 | theme.def(py::init(), D(Theme, Theme)) 11 | .def_readwrite("mFontNormal", &Theme::mFontNormal, D(Theme, mFontNormal)) 12 | .def_readwrite("mFontBold", &Theme::mFontBold, D(Theme, mFontBold)) 13 | .def_readwrite("mFontIcons", &Theme::mFontIcons, D(Theme, mFontIcons)) 14 | .def_readwrite("mIconScale", &Theme::mIconScale, D(Theme, mIconScale)) 15 | .def_readwrite("mStandardFontSize", &Theme::mStandardFontSize, D(Theme, mStandardFontSize)) 16 | .def_readwrite("mButtonFontSize", &Theme::mButtonFontSize, D(Theme, mButtonFontSize)) 17 | .def_readwrite("mTextBoxFontSize", &Theme::mTextBoxFontSize, D(Theme, mTextBoxFontSize)) 18 | .def_readwrite("mWindowCornerRadius", &Theme::mWindowCornerRadius, D(Theme, mWindowCornerRadius)) 19 | .def_readwrite("mWindowHeaderHeight", &Theme::mWindowHeaderHeight, D(Theme, mWindowHeaderHeight)) 20 | .def_readwrite("mWindowDropShadowSize", &Theme::mWindowDropShadowSize, D(Theme, mWindowDropShadowSize)) 21 | .def_readwrite("mButtonCornerRadius", &Theme::mButtonCornerRadius, D(Theme, mButtonCornerRadius)) 22 | .def_readwrite("mTabBorderWidth", &Theme::mTabBorderWidth, D(Theme, mTabBorderWidth)) 23 | .def_readwrite("mTabInnerMargin", &Theme::mTabInnerMargin, D(Theme, mTabInnerMargin)) 24 | .def_readwrite("mTabMinButtonWidth", &Theme::mTabMinButtonWidth, D(Theme, mTabMinButtonWidth)) 25 | .def_readwrite("mTabMaxButtonWidth", &Theme::mTabMaxButtonWidth, D(Theme, mTabMaxButtonWidth)) 26 | .def_readwrite("mTabControlWidth", &Theme::mTabControlWidth, D(Theme, mTabControlWidth)) 27 | .def_readwrite("mTabButtonHorizontalPadding", &Theme::mTabButtonHorizontalPadding, D(Theme, mTabButtonHorizontalPadding)) 28 | .def_readwrite("mTabButtonVerticalPadding", &Theme::mTabButtonVerticalPadding, D(Theme, mTabButtonVerticalPadding)) 29 | .def_readwrite("mDropShadow", &Theme::mDropShadow, D(Theme, mDropShadow)) 30 | .def_readwrite("mTransparent", &Theme::mTransparent, D(Theme, mTransparent)) 31 | .def_readwrite("mBorderDark", &Theme::mBorderDark, D(Theme, mBorderDark)) 32 | .def_readwrite("mBorderLight", &Theme::mBorderLight, D(Theme, mBorderLight)) 33 | .def_readwrite("mBorderMedium", &Theme::mBorderMedium, D(Theme, mBorderMedium)) 34 | .def_readwrite("mTextColor", &Theme::mTextColor, D(Theme, mTextColor)) 35 | .def_readwrite("mDisabledTextColor", &Theme::mDisabledTextColor, D(Theme, mDisabledTextColor)) 36 | .def_readwrite("mTextColorShadow", &Theme::mTextColorShadow, D(Theme, mTextColorShadow)) 37 | .def_readwrite("mIconColor", &Theme::mIconColor, D(Theme, mIconColor)) 38 | .def_readwrite("mButtonGradientTopFocused", &Theme::mButtonGradientTopFocused, D(Theme, mButtonGradientTopFocused)) 39 | .def_readwrite("mButtonGradientBotFocused", &Theme::mButtonGradientBotFocused, D(Theme, mButtonGradientBotFocused)) 40 | .def_readwrite("mButtonGradientTopUnfocused", &Theme::mButtonGradientTopUnfocused, D(Theme, mButtonGradientTopUnfocused)) 41 | .def_readwrite("mButtonGradientBotUnfocused", &Theme::mButtonGradientBotUnfocused, D(Theme, mButtonGradientBotUnfocused)) 42 | .def_readwrite("mButtonGradientTopPushed", &Theme::mButtonGradientTopPushed, D(Theme, mButtonGradientTopPushed)) 43 | .def_readwrite("mButtonGradientBotPushed", &Theme::mButtonGradientBotPushed, D(Theme, mButtonGradientBotPushed)) 44 | .def_readwrite("mWindowFillUnfocused", &Theme::mWindowFillUnfocused, D(Theme, mWindowFillUnfocused)) 45 | .def_readwrite("mWindowFillFocused", &Theme::mWindowFillFocused, D(Theme, mWindowFillFocused)) 46 | .def_readwrite("mWindowTitleUnfocused", &Theme::mWindowTitleUnfocused, D(Theme, mWindowTitleUnfocused)) 47 | .def_readwrite("mWindowTitleFocused", &Theme::mWindowTitleFocused, D(Theme, mWindowTitleFocused)) 48 | .def_readwrite("mWindowHeaderGradientTop", &Theme::mWindowHeaderGradientTop, D(Theme, mWindowHeaderGradientTop)) 49 | .def_readwrite("mWindowHeaderGradientBot", &Theme::mWindowHeaderGradientBot, D(Theme, mWindowHeaderGradientBot)) 50 | .def_readwrite("mWindowHeaderSepTop", &Theme::mWindowHeaderSepTop, D(Theme, mWindowHeaderSepTop)) 51 | .def_readwrite("mWindowHeaderSepBot", &Theme::mWindowHeaderSepBot, D(Theme, mWindowHeaderSepBot)) 52 | .def_readwrite("mWindowPopup", &Theme::mWindowPopup, D(Theme, mWindowPopup)) 53 | .def_readwrite("mWindowPopupTransparent", &Theme::mWindowPopupTransparent, D(Theme, mWindowPopupTransparent)) 54 | .def_readwrite("mCheckBoxIcon", &Theme::mCheckBoxIcon, D(Theme, mCheckBoxIcon)) 55 | .def_readwrite("mMessageInformationIcon", &Theme::mMessageInformationIcon, D(Theme, mMessageInformationIcon)) 56 | .def_readwrite("mMessageQuestionIcon", &Theme::mMessageQuestionIcon, D(Theme, mMessageQuestionIcon)) 57 | .def_readwrite("mMessageWarningIcon", &Theme::mMessageWarningIcon, D(Theme, mMessageWarningIcon)) 58 | .def_readwrite("mMessageAltButtonIcon", &Theme::mMessageAltButtonIcon, D(Theme, mMessageAltButtonIcon)) 59 | .def_readwrite("mMessagePrimaryButtonIcon", &Theme::mMessagePrimaryButtonIcon, D(Theme, mMessagePrimaryButtonIcon)) 60 | .def_readwrite("mPopupChevronRightIcon", &Theme::mPopupChevronRightIcon, D(Theme, mPopupChevronRightIcon)) 61 | .def_readwrite("mPopupChevronLeftIcon", &Theme::mPopupChevronLeftIcon, D(Theme, mPopupChevronLeftIcon)) 62 | .def_readwrite("mTabHeaderLeftIcon", &Theme::mTabHeaderLeftIcon, D(Theme, mTabHeaderLeftIcon)) 63 | .def_readwrite("mTabHeaderRightIcon", &Theme::mTabHeaderRightIcon, D(Theme, mTabHeaderRightIcon)) 64 | .def_readwrite("mTextBoxUpIcon", &Theme::mTextBoxUpIcon, D(Theme, mTextBoxUpIcon)) 65 | .def_readwrite("mTextBoxDownIcon", &Theme::mTextBoxDownIcon, D(Theme, mTextBoxDownIcon)); 66 | } 67 | -------------------------------------------------------------------------------- /resources/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/Roboto-Bold.ttf -------------------------------------------------------------------------------- /resources/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/Roboto-Regular.ttf -------------------------------------------------------------------------------- /resources/bin2c.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8.12) 2 | 3 | # Create header for C file 4 | file(WRITE ${OUTPUT_C} "/* Autogenerated by bin2c */\n\n") 5 | file(APPEND ${OUTPUT_C} "#include \n\n") 6 | 7 | # Create header of H file 8 | file(WRITE ${OUTPUT_H} "/* Autogenerated by bin2c */\n\n") 9 | file(APPEND ${OUTPUT_H} "#pragma once\n") 10 | file(APPEND ${OUTPUT_H} "#include \n\n") 11 | 12 | string(REPLACE "," ";" INPUT_LIST ${INPUT_FILES}) 13 | 14 | 15 | # Iterate through binary files files 16 | foreach(bin ${INPUT_LIST}) 17 | # Get short filename 18 | string(REGEX MATCH "([^/]+)$" filename ${bin}) 19 | # Replace filename spaces & extension separator for C compatibility 20 | string(REGEX REPLACE "\\.| |-" "_" filename ${filename}) 21 | # Convert to lower case 22 | string(TOLOWER ${filename} filename) 23 | # Read hex data from file 24 | file(READ ${bin} filedata HEX) 25 | # Convert hex data for C compatibility 26 | string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," filedata ${filedata}) 27 | # Append data to c file 28 | file(APPEND ${OUTPUT_C} "uint8_t ${filename}[] = {${filedata}};\n\nuint32_t ${filename}_size = sizeof(${filename});\n\n") 29 | # Append extern definitions to h file 30 | file(APPEND ${OUTPUT_H} "extern uint8_t ${filename}[];\n\nextern uint32_t ${filename}_size;\n\n") 31 | endforeach() 32 | -------------------------------------------------------------------------------- /resources/check-style.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Script to check include/test code for common pybind11 code style errors. 4 | # 5 | # This script currently checks for 6 | # 7 | # 1. use of tabs instead of spaces 8 | # 2. MSDOS-style CRLF endings 9 | # 3. trailing spaces 10 | # 4. missing space between keyword and parenthesis, e.g.: for(, if(, while( 11 | # 5. Missing space between right parenthesis and brace, e.g. 'for (...){' 12 | # 6. opening brace on its own line. It should always be on the same line as the 13 | # if/while/for/do statment. 14 | # 15 | # Invoke as: tools/check-style.sh 16 | # 17 | 18 | errors=0 19 | IFS=$'\n' 20 | found= 21 | # The mt=41 sets a red background for matched tabs: 22 | exec 3< <(GREP_COLORS='mt=41' grep $'\t' include/ src/ python/*.{h,cpp} docs/*.rst -rn --color=always) 23 | while read -u 3 f; do 24 | if [ -z "$found" ]; then 25 | echo -e '\e[31m\e[01mError: found tabs instead of spaces in the following files:\e[0m' 26 | found=1 27 | errors=1 28 | fi 29 | 30 | echo " $f" 31 | done 32 | 33 | found= 34 | # The mt=41 sets a red background for matched MS-DOS CRLF characters 35 | exec 3< <(GREP_COLORS='mt=41' grep -IUlr $'\r' include/ src/ python/*.{h,cpp} docs/*.rst --color=always) 36 | while read -u 3 f; do 37 | if [ -z "$found" ]; then 38 | echo -e '\e[31m\e[01mError: found CRLF characters in the following files:\e[0m' 39 | found=1 40 | errors=1 41 | fi 42 | 43 | echo " $f" 44 | done 45 | 46 | found= 47 | # The mt=41 sets a red background for matched trailing spaces 48 | exec 3< <(GREP_COLORS='mt=41' grep '\s\+$' include/ src/ python/*.{h,cpp} docs/*.rst -rn --color=always) 49 | while read -u 3 f; do 50 | if [ -z "$found" ]; then 51 | echo -e '\e[31m\e[01mError: found trailing spaces in the following files:\e[0m' 52 | found=1 53 | errors=1 54 | fi 55 | 56 | echo " $f" 57 | done 58 | 59 | found= 60 | exec 3< <(grep '\<\(if\|for\|while\|catch\)(\|){' include/ src/ python/*.{h,cpp} -rn --color=always) 61 | while read -u 3 line; do 62 | if [ -z "$found" ]; then 63 | echo -e '\e[31m\e[01mError: found the following coding style problems:\e[0m' 64 | found=1 65 | errors=1 66 | fi 67 | 68 | echo " $line" 69 | done 70 | 71 | found= 72 | exec 3< <(GREP_COLORS='mt=41' grep '^\s*{\s*$' include/ src/ -rn --color=always) 73 | while read -u 3 f; do 74 | if [ -z "$found" ]; then 75 | echo -e '\e[31m\e[01mError: braces should occur on the same line as the if/while/.. statement. Found issues in the following files: \e[0m' 76 | found=1 77 | errors=1 78 | fi 79 | 80 | echo " $f" 81 | done 82 | 83 | exit $errors 84 | -------------------------------------------------------------------------------- /resources/entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/entypo.ttf -------------------------------------------------------------------------------- /resources/icons/icon1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/icons/icon1.png -------------------------------------------------------------------------------- /resources/icons/icon2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/icons/icon2.png -------------------------------------------------------------------------------- /resources/icons/icon3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/icons/icon3.png -------------------------------------------------------------------------------- /resources/icons/icon4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/icons/icon4.png -------------------------------------------------------------------------------- /resources/icons/icon5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/icons/icon5.png -------------------------------------------------------------------------------- /resources/icons/icon6.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/icons/icon6.ico -------------------------------------------------------------------------------- /resources/icons/icon6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/icons/icon6.png -------------------------------------------------------------------------------- /resources/icons/icon7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/icons/icon7.png -------------------------------------------------------------------------------- /resources/icons/icon8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/icons/icon8.png -------------------------------------------------------------------------------- /resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/screenshot.png -------------------------------------------------------------------------------- /resources/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjakob/nanogui/e9ec8a1a9861cf578d9c6e85a6420080aa715c03/resources/screenshot2.png -------------------------------------------------------------------------------- /src/checkbox.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/checkbox.cpp -- Two-state check box widget 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | CheckBox::CheckBox(Widget *parent, const std::string &caption, 20 | const std::function &callback) 21 | : Widget(parent), mCaption(caption), mPushed(false), mChecked(false), 22 | mCallback(callback) { 23 | 24 | mIconExtraScale = 1.2f;// widget override 25 | } 26 | 27 | bool CheckBox::mouseButtonEvent(const Vector2i &p, int button, bool down, 28 | int modifiers) { 29 | Widget::mouseButtonEvent(p, button, down, modifiers); 30 | if (!mEnabled) 31 | return false; 32 | 33 | if (button == GLFW_MOUSE_BUTTON_1) { 34 | if (down) { 35 | mPushed = true; 36 | } else if (mPushed) { 37 | if (contains(p)) { 38 | mChecked = !mChecked; 39 | if (mCallback) 40 | mCallback(mChecked); 41 | } 42 | mPushed = false; 43 | } 44 | return true; 45 | } 46 | return false; 47 | } 48 | 49 | Vector2i CheckBox::preferredSize(NVGcontext *ctx) const { 50 | if (mFixedSize != Vector2i::Zero()) 51 | return mFixedSize; 52 | nvgFontSize(ctx, fontSize()); 53 | nvgFontFace(ctx, "sans"); 54 | return Vector2i( 55 | nvgTextBounds(ctx, 0, 0, mCaption.c_str(), nullptr, nullptr) + 56 | 1.8f * fontSize(), 57 | fontSize() * 1.3f); 58 | } 59 | 60 | void CheckBox::draw(NVGcontext *ctx) { 61 | Widget::draw(ctx); 62 | 63 | nvgFontSize(ctx, fontSize()); 64 | nvgFontFace(ctx, "sans"); 65 | nvgFillColor(ctx, 66 | mEnabled ? mTheme->mTextColor : mTheme->mDisabledTextColor); 67 | nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); 68 | nvgText(ctx, mPos.x() + 1.6f * fontSize(), mPos.y() + mSize.y() * 0.5f, 69 | mCaption.c_str(), nullptr); 70 | 71 | NVGpaint bg = nvgBoxGradient(ctx, mPos.x() + 1.5f, mPos.y() + 1.5f, 72 | mSize.y() - 2.0f, mSize.y() - 2.0f, 3, 3, 73 | mPushed ? Color(0, 100) : Color(0, 32), 74 | Color(0, 0, 0, 180)); 75 | 76 | nvgBeginPath(ctx); 77 | nvgRoundedRect(ctx, mPos.x() + 1.0f, mPos.y() + 1.0f, mSize.y() - 2.0f, 78 | mSize.y() - 2.0f, 3); 79 | nvgFillPaint(ctx, bg); 80 | nvgFill(ctx); 81 | 82 | if (mChecked) { 83 | nvgFontSize(ctx, mSize.y() * icon_scale()); 84 | nvgFontFace(ctx, "icons"); 85 | nvgFillColor(ctx, mEnabled ? mTheme->mIconColor 86 | : mTheme->mDisabledTextColor); 87 | nvgTextAlign(ctx, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE); 88 | nvgText(ctx, mPos.x() + mSize.y() * 0.5f + 1, 89 | mPos.y() + mSize.y() * 0.5f, utf8(mTheme->mCheckBoxIcon).data(), 90 | nullptr); 91 | } 92 | } 93 | 94 | void CheckBox::save(Serializer &s) const { 95 | Widget::save(s); 96 | s.set("caption", mCaption); 97 | s.set("pushed", mPushed); 98 | s.set("checked", mChecked); 99 | } 100 | 101 | bool CheckBox::load(Serializer &s) { 102 | if (!Widget::load(s)) return false; 103 | if (!s.get("caption", mCaption)) return false; 104 | if (!s.get("pushed", mPushed)) return false; 105 | if (!s.get("checked", mChecked)) return false; 106 | return true; 107 | } 108 | 109 | NAMESPACE_END(nanogui) 110 | -------------------------------------------------------------------------------- /src/colorpicker.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/colorpicker.cpp -- push button with a popup to tweak a color value 3 | 4 | This widget was contributed by Christian Schueller. 5 | 6 | NanoGUI was developed by Wenzel Jakob . 7 | The widget drawing code is based on the NanoVG demo application 8 | by Mikko Mononen. 9 | 10 | All rights reserved. Use of this source code is governed by a 11 | BSD-style license that can be found in the LICENSE.txt file. 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | NAMESPACE_BEGIN(nanogui) 19 | 20 | ColorPicker::ColorPicker(Widget *parent, const Color& color) : PopupButton(parent, "") { 21 | setBackgroundColor(color); 22 | Popup *popup = this->popup(); 23 | popup->setLayout(new GroupLayout()); 24 | 25 | // initialize callback to do nothing; this is for users to hook into 26 | // receiving a new color value 27 | mCallback = [](const Color &) {}; 28 | mFinalCallback = [](const Color &) {}; 29 | 30 | // set the color wheel to the specified color 31 | mColorWheel = new ColorWheel(popup, color); 32 | 33 | // set the pick button to the specified color 34 | mPickButton = new Button(popup, "Pick"); 35 | mPickButton->setBackgroundColor(color); 36 | mPickButton->setTextColor(color.contrastingColor()); 37 | mPickButton->setFixedSize(Vector2i(100, 20)); 38 | 39 | // set the reset button to the specified color 40 | mResetButton = new Button(popup, "Reset"); 41 | mResetButton->setBackgroundColor(color); 42 | mResetButton->setTextColor(color.contrastingColor()); 43 | mResetButton->setFixedSize(Vector2i(100, 20)); 44 | 45 | PopupButton::setChangeCallback([&](bool) { 46 | if (this->mPickButton->pushed()) { 47 | setColor(backgroundColor()); 48 | mFinalCallback(backgroundColor()); 49 | } 50 | }); 51 | 52 | mColorWheel->setCallback([&](const Color &value) { 53 | mPickButton->setBackgroundColor(value); 54 | mPickButton->setTextColor(value.contrastingColor()); 55 | mCallback(value); 56 | }); 57 | 58 | mPickButton->setCallback([this]() { 59 | if (mPushed) { 60 | Color value = mColorWheel->color(); 61 | setPushed(false); 62 | setColor(value); 63 | mFinalCallback(value); 64 | } 65 | }); 66 | 67 | mResetButton->setCallback([this]() { 68 | Color bg = this->mResetButton->backgroundColor(); 69 | Color fg = this->mResetButton->textColor(); 70 | 71 | mColorWheel->setColor(bg); 72 | mPickButton->setBackgroundColor(bg); 73 | mPickButton->setTextColor(fg); 74 | 75 | mCallback(bg); 76 | mFinalCallback(bg); 77 | }); 78 | } 79 | 80 | Color ColorPicker::color() const { 81 | return backgroundColor(); 82 | } 83 | 84 | void ColorPicker::setColor(const Color& color) { 85 | /* Ignore setColor() calls when the user is currently editing */ 86 | if (!mPushed) { 87 | Color fg = color.contrastingColor(); 88 | setBackgroundColor(color); 89 | setTextColor(fg); 90 | mColorWheel->setColor(color); 91 | 92 | mPickButton->setBackgroundColor(color); 93 | mPickButton->setTextColor(fg); 94 | 95 | mResetButton->setBackgroundColor(color); 96 | mResetButton->setTextColor(fg); 97 | } 98 | } 99 | 100 | NAMESPACE_END(nanogui) 101 | -------------------------------------------------------------------------------- /src/combobox.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/combobox.cpp -- simple combo box widget based on a popup button 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | ComboBox::ComboBox(Widget *parent) : PopupButton(parent), mSelectedIndex(0) { 20 | } 21 | 22 | ComboBox::ComboBox(Widget *parent, const std::vector &items) 23 | : PopupButton(parent), mSelectedIndex(0) { 24 | setItems(items); 25 | } 26 | 27 | ComboBox::ComboBox(Widget *parent, const std::vector &items, const std::vector &itemsShort) 28 | : PopupButton(parent), mSelectedIndex(0) { 29 | setItems(items, itemsShort); 30 | } 31 | 32 | void ComboBox::setSelectedIndex(int idx) { 33 | if (mItemsShort.empty()) 34 | return; 35 | const std::vector &children = popup()->children(); 36 | ((Button *) children[mSelectedIndex])->setPushed(false); 37 | ((Button *) children[idx])->setPushed(true); 38 | mSelectedIndex = idx; 39 | setCaption(mItemsShort[idx]); 40 | } 41 | 42 | void ComboBox::setItems(const std::vector &items, const std::vector &itemsShort) { 43 | assert(items.size() == itemsShort.size()); 44 | mItems = items; 45 | mItemsShort = itemsShort; 46 | if (mSelectedIndex < 0 || mSelectedIndex >= (int) items.size()) 47 | mSelectedIndex = 0; 48 | while (mPopup->childCount() != 0) 49 | mPopup->removeChild(mPopup->childCount()-1); 50 | mPopup->setLayout(new GroupLayout(10)); 51 | int index = 0; 52 | for (const auto &str: items) { 53 | Button *button = new Button(mPopup, str); 54 | button->setFlags(Button::RadioButton); 55 | button->setCallback([&, index] { 56 | mSelectedIndex = index; 57 | setCaption(mItemsShort[index]); 58 | setPushed(false); 59 | popup()->setVisible(false); 60 | if (mCallback) 61 | mCallback(index); 62 | }); 63 | index++; 64 | } 65 | setSelectedIndex(mSelectedIndex); 66 | } 67 | 68 | bool ComboBox::scrollEvent(const Vector2i &p, const Vector2f &rel) { 69 | if (rel.y() < 0) { 70 | setSelectedIndex(std::min(mSelectedIndex+1, (int)(items().size()-1))); 71 | if (mCallback) 72 | mCallback(mSelectedIndex); 73 | return true; 74 | } else if (rel.y() > 0) { 75 | setSelectedIndex(std::max(mSelectedIndex-1, 0)); 76 | if (mCallback) 77 | mCallback(mSelectedIndex); 78 | return true; 79 | } 80 | return Widget::scrollEvent(p, rel); 81 | } 82 | 83 | void ComboBox::save(Serializer &s) const { 84 | Widget::save(s); 85 | s.set("items", mItems); 86 | s.set("itemsShort", mItemsShort); 87 | s.set("selectedIndex", mSelectedIndex); 88 | } 89 | 90 | bool ComboBox::load(Serializer &s) { 91 | if (!Widget::load(s)) return false; 92 | if (!s.get("items", mItems)) return false; 93 | if (!s.get("itemsShort", mItemsShort)) return false; 94 | if (!s.get("selectedIndex", mSelectedIndex)) return false; 95 | return true; 96 | } 97 | 98 | NAMESPACE_END(nanogui) 99 | -------------------------------------------------------------------------------- /src/darwin.mm: -------------------------------------------------------------------------------- 1 | #include 2 | #import 3 | 4 | NAMESPACE_BEGIN(nanogui) 5 | 6 | std::vector file_dialog(const std::vector> &filetypes, bool save, bool multiple) { 7 | if (save && multiple) { 8 | throw std::invalid_argument("save and multiple must not both be true."); 9 | } 10 | 11 | std::vector result; 12 | if (save) { 13 | NSSavePanel *saveDlg = [NSSavePanel savePanel]; 14 | 15 | NSMutableArray *types = [NSMutableArray new]; 16 | for (size_t idx = 0; idx < filetypes.size(); ++idx) 17 | [types addObject: [NSString stringWithUTF8String: filetypes[idx].first.c_str()]]; 18 | 19 | [saveDlg setAllowedFileTypes: types]; 20 | 21 | if ([saveDlg runModal] == NSModalResponseOK) 22 | result.emplace_back([[[saveDlg URL] path] UTF8String]); 23 | } else { 24 | NSOpenPanel *openDlg = [NSOpenPanel openPanel]; 25 | 26 | [openDlg setCanChooseFiles:YES]; 27 | [openDlg setCanChooseDirectories:NO]; 28 | [openDlg setAllowsMultipleSelection:multiple]; 29 | NSMutableArray *types = [NSMutableArray new]; 30 | for (size_t idx = 0; idx < filetypes.size(); ++idx) 31 | [types addObject: [NSString stringWithUTF8String: filetypes[idx].first.c_str()]]; 32 | 33 | [openDlg setAllowedFileTypes: types]; 34 | 35 | if ([openDlg runModal] == NSModalResponseOK) { 36 | for (NSURL* url in [openDlg URLs]) { 37 | result.emplace_back((char*) [[url path] UTF8String]); 38 | } 39 | } 40 | } 41 | return result; 42 | } 43 | 44 | void chdir_to_bundle_parent() { 45 | NSString *path = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent]; 46 | chdir([path fileSystemRepresentation]); 47 | } 48 | 49 | void disable_saved_application_state_osx() { 50 | [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"NSQuitAlwaysKeepsWindows"]; 51 | } 52 | 53 | NAMESPACE_END(nanogui) 54 | -------------------------------------------------------------------------------- /src/example2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/example2.cpp -- C++ version of an example application that shows 3 | how to use the form helper class. For a Python implementation, see 4 | '../python/example2.py'. 5 | 6 | NanoGUI was developed by Wenzel Jakob . 7 | The widget drawing code is based on the NanoVG demo application 8 | by Mikko Mononen. 9 | 10 | All rights reserved. Use of this source code is governed by a 11 | BSD-style license that can be found in the LICENSE.txt file. 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | using namespace nanogui; 18 | 19 | enum test_enum { 20 | Item1 = 0, 21 | Item2, 22 | Item3 23 | }; 24 | 25 | bool bvar = true; 26 | int ivar = 12345678; 27 | double dvar = 3.1415926; 28 | float fvar = (float)dvar; 29 | std::string strval = "A string"; 30 | test_enum enumval = Item2; 31 | Color colval(0.5f, 0.5f, 0.7f, 1.f); 32 | 33 | int main(int /* argc */, char ** /* argv */) { 34 | nanogui::init(); 35 | 36 | /* scoped variables */ { 37 | bool use_gl_4_1 = false;// Set to true to create an OpenGL 4.1 context. 38 | Screen *screen = nullptr; 39 | 40 | if (use_gl_4_1) { 41 | // NanoGUI presents many options for you to utilize at your discretion. 42 | // See include/nanogui/screen.h for what all of these represent. 43 | screen = new Screen(Vector2i(500, 700), "NanoGUI test [GL 4.1]", 44 | /*resizable*/true, /*fullscreen*/false, /*colorBits*/8, 45 | /*alphaBits*/8, /*depthBits*/24, /*stencilBits*/8, 46 | /*nSamples*/0, /*glMajor*/4, /*glMinor*/1); 47 | } else { 48 | screen = new Screen(Vector2i(500, 700), "NanoGUI test"); 49 | } 50 | 51 | bool enabled = true; 52 | FormHelper *gui = new FormHelper(screen); 53 | ref window = gui->addWindow(Eigen::Vector2i(10, 10), "Form helper example"); 54 | gui->addGroup("Basic types"); 55 | gui->addVariable("bool", bvar); 56 | gui->addVariable("string", strval); 57 | 58 | gui->addGroup("Validating fields"); 59 | gui->addVariable("int", ivar)->setSpinnable(true); 60 | gui->addVariable("float", fvar); 61 | gui->addVariable("double", dvar)->setSpinnable(true); 62 | 63 | gui->addGroup("Complex types"); 64 | gui->addVariable("Enumeration", enumval, enabled) 65 | ->setItems({"Item 1", "Item 2", "Item 3"}); 66 | gui->addVariable("Color", colval) 67 | ->setFinalCallback([](const Color &c) { 68 | std::cout << "ColorPicker Final Callback: [" 69 | << c.r() << ", " 70 | << c.g() << ", " 71 | << c.b() << ", " 72 | << c.w() << "]" << std::endl; 73 | }); 74 | 75 | gui->addGroup("Other widgets"); 76 | gui->addButton("A button", []() { std::cout << "Button pressed." << std::endl; }); 77 | 78 | screen->setVisible(true); 79 | screen->performLayout(); 80 | window->center(); 81 | 82 | nanogui::mainloop(); 83 | } 84 | 85 | nanogui::shutdown(); 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /src/example3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/example3.cpp -- C++ version of an example application that shows 3 | how to use nanogui in an application with an already created and managed 4 | glfw context. 5 | 6 | NanoGUI was developed by Wenzel Jakob . 7 | The widget drawing code is based on the NanoVG demo application 8 | by Mikko Mononen. 9 | 10 | All rights reserved. Use of this source code is governed by a 11 | BSD-style license that can be found in the LICENSE.txt file. 12 | */ 13 | 14 | // GLFW 15 | // 16 | #if defined(NANOGUI_GLAD) 17 | #if defined(NANOGUI_SHARED) && !defined(GLAD_GLAPI_EXPORT) 18 | #define GLAD_GLAPI_EXPORT 19 | #endif 20 | 21 | #include 22 | #else 23 | #if defined(__APPLE__) 24 | #define GLFW_INCLUDE_GLCOREARB 25 | #else 26 | #define GL_GLEXT_PROTOTYPES 27 | #endif 28 | #endif 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | using namespace nanogui; 36 | 37 | enum test_enum { 38 | Item1 = 0, 39 | Item2, 40 | Item3 41 | }; 42 | 43 | bool bvar = true; 44 | int ivar = 12345678; 45 | double dvar = 3.1415926; 46 | float fvar = (float)dvar; 47 | std::string strval = "A string"; 48 | test_enum enumval = Item2; 49 | Color colval(0.5f, 0.5f, 0.7f, 1.f); 50 | 51 | Screen *screen = nullptr; 52 | 53 | int main(int /* argc */, char ** /* argv */) { 54 | 55 | glfwInit(); 56 | 57 | glfwSetTime(0); 58 | 59 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 60 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 61 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 62 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 63 | 64 | glfwWindowHint(GLFW_SAMPLES, 0); 65 | glfwWindowHint(GLFW_RED_BITS, 8); 66 | glfwWindowHint(GLFW_GREEN_BITS, 8); 67 | glfwWindowHint(GLFW_BLUE_BITS, 8); 68 | glfwWindowHint(GLFW_ALPHA_BITS, 8); 69 | glfwWindowHint(GLFW_STENCIL_BITS, 8); 70 | glfwWindowHint(GLFW_DEPTH_BITS, 24); 71 | glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); 72 | 73 | // Create a GLFWwindow object 74 | GLFWwindow* window = glfwCreateWindow(800, 800, "example3", nullptr, nullptr); 75 | if (window == nullptr) { 76 | std::cout << "Failed to create GLFW window" << std::endl; 77 | glfwTerminate(); 78 | return -1; 79 | } 80 | glfwMakeContextCurrent(window); 81 | 82 | #if defined(NANOGUI_GLAD) 83 | if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) 84 | throw std::runtime_error("Could not initialize GLAD!"); 85 | glGetError(); // pull and ignore unhandled errors like GL_INVALID_ENUM 86 | #endif 87 | 88 | glClearColor(0.2f, 0.25f, 0.3f, 1.0f); 89 | glClear(GL_COLOR_BUFFER_BIT); 90 | 91 | // Create a nanogui screen and pass the glfw pointer to initialize 92 | screen = new Screen(); 93 | screen->initialize(window, true); 94 | 95 | int width, height; 96 | glfwGetFramebufferSize(window, &width, &height); 97 | glViewport(0, 0, width, height); 98 | glfwSwapInterval(0); 99 | glfwSwapBuffers(window); 100 | 101 | // Create nanogui gui 102 | bool enabled = true; 103 | FormHelper *gui = new FormHelper(screen); 104 | ref nanoguiWindow = gui->addWindow(Eigen::Vector2i(10, 10), "Form helper example"); 105 | gui->addGroup("Basic types"); 106 | gui->addVariable("bool", bvar)->setTooltip("Test tooltip."); 107 | gui->addVariable("string", strval); 108 | 109 | gui->addGroup("Validating fields"); 110 | gui->addVariable("int", ivar)->setSpinnable(true); 111 | gui->addVariable("float", fvar)->setTooltip("Test."); 112 | gui->addVariable("double", dvar)->setSpinnable(true); 113 | 114 | gui->addGroup("Complex types"); 115 | gui->addVariable("Enumeration", enumval, enabled)->setItems({ "Item 1", "Item 2", "Item 3" }); 116 | gui->addVariable("Color", colval) 117 | ->setFinalCallback([](const Color &c) { 118 | std::cout << "ColorPicker Final Callback: [" 119 | << c.r() << ", " 120 | << c.g() << ", " 121 | << c.b() << ", " 122 | << c.w() << "]" << std::endl; 123 | }); 124 | 125 | gui->addGroup("Other widgets"); 126 | gui->addButton("A button", []() { std::cout << "Button pressed." << std::endl; })->setTooltip("Testing a much longer tooltip, that will wrap around to new lines multiple times.");; 127 | 128 | screen->setVisible(true); 129 | screen->performLayout(); 130 | nanoguiWindow->center(); 131 | 132 | glfwSetCursorPosCallback(window, 133 | [](GLFWwindow *, double x, double y) { 134 | screen->cursorPosCallbackEvent(x, y); 135 | } 136 | ); 137 | 138 | glfwSetMouseButtonCallback(window, 139 | [](GLFWwindow *, int button, int action, int modifiers) { 140 | screen->mouseButtonCallbackEvent(button, action, modifiers); 141 | } 142 | ); 143 | 144 | glfwSetKeyCallback(window, 145 | [](GLFWwindow *, int key, int scancode, int action, int mods) { 146 | screen->keyCallbackEvent(key, scancode, action, mods); 147 | } 148 | ); 149 | 150 | glfwSetCharCallback(window, 151 | [](GLFWwindow *, unsigned int codepoint) { 152 | screen->charCallbackEvent(codepoint); 153 | } 154 | ); 155 | 156 | glfwSetDropCallback(window, 157 | [](GLFWwindow *, int count, const char **filenames) { 158 | screen->dropCallbackEvent(count, filenames); 159 | } 160 | ); 161 | 162 | glfwSetScrollCallback(window, 163 | [](GLFWwindow *, double x, double y) { 164 | screen->scrollCallbackEvent(x, y); 165 | } 166 | ); 167 | 168 | glfwSetFramebufferSizeCallback(window, 169 | [](GLFWwindow *, int width, int height) { 170 | screen->resizeCallbackEvent(width, height); 171 | } 172 | ); 173 | 174 | // Game loop 175 | while (!glfwWindowShouldClose(window)) { 176 | // Check if any events have been activated (key pressed, mouse moved etc.) and call corresponding response functions 177 | glfwPollEvents(); 178 | 179 | glClearColor(0.2f, 0.25f, 0.3f, 1.0f); 180 | glClear(GL_COLOR_BUFFER_BIT); 181 | 182 | // Draw nanogui 183 | screen->drawContents(); 184 | screen->drawWidgets(); 185 | 186 | glfwSwapBuffers(window); 187 | } 188 | 189 | // Terminate GLFW, clearing any resources allocated by GLFW. 190 | glfwTerminate(); 191 | 192 | return 0; 193 | } 194 | -------------------------------------------------------------------------------- /src/glcanvas.cpp: -------------------------------------------------------------------------------- 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 . 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 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 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(); 54 | Vector2i positionInScreen = absolutePosition(); 55 | 56 | Vector2i size = (mSize.cast() * pixelRatio).cast(), 57 | imagePosition = (Vector2f(positionInScreen[0], 58 | screenSize[1] - positionInScreen[1] - 59 | (float) mSize[1]) * pixelRatio).cast(); 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 | -------------------------------------------------------------------------------- /src/graph.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/graph.cpp -- Simple graph widget for showing a function plot 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | Graph::Graph(Widget *parent, const std::string &caption) 20 | : Widget(parent), mCaption(caption) { 21 | mBackgroundColor = Color(20, 128); 22 | mForegroundColor = Color(255, 192, 0, 128); 23 | mTextColor = Color(240, 192); 24 | } 25 | 26 | Vector2i Graph::preferredSize(NVGcontext *) const { 27 | return Vector2i(180, 45); 28 | } 29 | 30 | void Graph::draw(NVGcontext *ctx) { 31 | Widget::draw(ctx); 32 | 33 | nvgBeginPath(ctx); 34 | nvgRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y()); 35 | nvgFillColor(ctx, mBackgroundColor); 36 | nvgFill(ctx); 37 | 38 | if (mValues.size() < 2) 39 | return; 40 | 41 | nvgBeginPath(ctx); 42 | nvgMoveTo(ctx, mPos.x(), mPos.y()+mSize.y()); 43 | for (size_t i = 0; i < (size_t) mValues.size(); i++) { 44 | float value = mValues[i]; 45 | float vx = mPos.x() + i * mSize.x() / (float) (mValues.size() - 1); 46 | float vy = mPos.y() + (1-value) * mSize.y(); 47 | nvgLineTo(ctx, vx, vy); 48 | } 49 | 50 | nvgLineTo(ctx, mPos.x() + mSize.x(), mPos.y() + mSize.y()); 51 | nvgStrokeColor(ctx, Color(100, 255)); 52 | nvgStroke(ctx); 53 | nvgFillColor(ctx, mForegroundColor); 54 | nvgFill(ctx); 55 | 56 | nvgFontFace(ctx, "sans"); 57 | 58 | if (!mCaption.empty()) { 59 | nvgFontSize(ctx, 14.0f); 60 | nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); 61 | nvgFillColor(ctx, mTextColor); 62 | nvgText(ctx, mPos.x() + 3, mPos.y() + 1, mCaption.c_str(), NULL); 63 | } 64 | 65 | if (!mHeader.empty()) { 66 | nvgFontSize(ctx, 18.0f); 67 | nvgTextAlign(ctx, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP); 68 | nvgFillColor(ctx, mTextColor); 69 | nvgText(ctx, mPos.x() + mSize.x() - 3, mPos.y() + 1, mHeader.c_str(), NULL); 70 | } 71 | 72 | if (!mFooter.empty()) { 73 | nvgFontSize(ctx, 15.0f); 74 | nvgTextAlign(ctx, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM); 75 | nvgFillColor(ctx, mTextColor); 76 | nvgText(ctx, mPos.x() + mSize.x() - 3, mPos.y() + mSize.y() - 1, mFooter.c_str(), NULL); 77 | } 78 | 79 | nvgBeginPath(ctx); 80 | nvgRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y()); 81 | nvgStrokeColor(ctx, Color(100, 255)); 82 | nvgStroke(ctx); 83 | } 84 | 85 | void Graph::save(Serializer &s) const { 86 | Widget::save(s); 87 | s.set("caption", mCaption); 88 | s.set("header", mHeader); 89 | s.set("footer", mFooter); 90 | s.set("backgroundColor", mBackgroundColor); 91 | s.set("foregroundColor", mForegroundColor); 92 | s.set("textColor", mTextColor); 93 | s.set("values", mValues); 94 | } 95 | 96 | bool Graph::load(Serializer &s) { 97 | if (!Widget::load(s)) return false; 98 | if (!s.get("caption", mCaption)) return false; 99 | if (!s.get("header", mHeader)) return false; 100 | if (!s.get("footer", mFooter)) return false; 101 | if (!s.get("backgroundColor", mBackgroundColor)) return false; 102 | if (!s.get("foregroundColor", mForegroundColor)) return false; 103 | if (!s.get("textColor", mTextColor)) return false; 104 | if (!s.get("values", mValues)) return false; 105 | return true; 106 | } 107 | 108 | NAMESPACE_END(nanogui) 109 | -------------------------------------------------------------------------------- /src/imagepanel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/imagepanel.cpp -- Image panel widget which shows a number of 3 | square-shaped icons 4 | 5 | NanoGUI was developed by Wenzel Jakob . 6 | The widget drawing code is based on the NanoVG demo application 7 | by Mikko Mononen. 8 | 9 | All rights reserved. Use of this source code is governed by a 10 | BSD-style license that can be found in the LICENSE.txt file. 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | NAMESPACE_BEGIN(nanogui) 17 | 18 | ImagePanel::ImagePanel(Widget *parent) 19 | : Widget(parent), mThumbSize(64), mSpacing(10), mMargin(10), 20 | mMouseIndex(-1) {} 21 | 22 | Vector2i ImagePanel::gridSize() const { 23 | int nCols = 1 + std::max(0, 24 | (int) ((mSize.x() - 2 * mMargin - mThumbSize) / 25 | (float) (mThumbSize + mSpacing))); 26 | int nRows = ((int) mImages.size() + nCols - 1) / nCols; 27 | return Vector2i(nCols, nRows); 28 | } 29 | 30 | int ImagePanel::indexForPosition(const Vector2i &p) const { 31 | Vector2f pp = ((p - mPos).cast() - Vector2f::Constant(mMargin)) / 32 | (float)(mThumbSize + mSpacing); 33 | float iconRegion = mThumbSize / (float)(mThumbSize + mSpacing); 34 | bool overImage = pp.x() - std::floor(pp.x()) < iconRegion && 35 | pp.y() - std::floor(pp.y()) < iconRegion; 36 | Vector2i gridPos = pp.cast(), grid = gridSize(); 37 | overImage &= ((gridPos.array() >= 0).all() && 38 | (gridPos.array() < grid.array()).all()); 39 | return overImage ? (gridPos.x() + gridPos.y() * grid.x()) : -1; 40 | } 41 | 42 | bool ImagePanel::mouseMotionEvent(const Vector2i &p, const Vector2i & /* rel */, 43 | int /* button */, int /* modifiers */) { 44 | mMouseIndex = indexForPosition(p); 45 | return true; 46 | } 47 | 48 | bool ImagePanel::mouseButtonEvent(const Vector2i &p, int /* button */, bool down, 49 | int /* modifiers */) { 50 | int index = indexForPosition(p); 51 | if (index >= 0 && index < (int) mImages.size() && mCallback && down) 52 | mCallback(index); 53 | return true; 54 | } 55 | 56 | Vector2i ImagePanel::preferredSize(NVGcontext *) const { 57 | Vector2i grid = gridSize(); 58 | return Vector2i( 59 | grid.x() * mThumbSize + (grid.x() - 1) * mSpacing + 2*mMargin, 60 | grid.y() * mThumbSize + (grid.y() - 1) * mSpacing + 2*mMargin 61 | ); 62 | } 63 | 64 | void ImagePanel::draw(NVGcontext* ctx) { 65 | Vector2i grid = gridSize(); 66 | 67 | for (size_t i=0; i. 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | Label::Label(Widget *parent, const std::string &caption, const std::string &font, int fontSize) 20 | : Widget(parent), mCaption(caption), mFont(font) { 21 | if (mTheme) { 22 | mFontSize = mTheme->mStandardFontSize; 23 | mColor = mTheme->mTextColor; 24 | } 25 | if (fontSize >= 0) mFontSize = fontSize; 26 | } 27 | 28 | void Label::setTheme(Theme *theme) { 29 | Widget::setTheme(theme); 30 | if (mTheme) { 31 | mFontSize = mTheme->mStandardFontSize; 32 | mColor = mTheme->mTextColor; 33 | } 34 | } 35 | 36 | Vector2i Label::preferredSize(NVGcontext *ctx) const { 37 | if (mCaption == "") 38 | return Vector2i::Zero(); 39 | nvgFontFace(ctx, mFont.c_str()); 40 | nvgFontSize(ctx, fontSize()); 41 | if (mFixedSize.x() > 0) { 42 | float bounds[4]; 43 | nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); 44 | nvgTextBoxBounds(ctx, mPos.x(), mPos.y(), mFixedSize.x(), mCaption.c_str(), nullptr, bounds); 45 | return Vector2i(mFixedSize.x(), bounds[3] - bounds[1]); 46 | } else { 47 | nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); 48 | return Vector2i( 49 | nvgTextBounds(ctx, 0, 0, mCaption.c_str(), nullptr, nullptr) + 2, 50 | fontSize() 51 | ); 52 | } 53 | } 54 | 55 | void Label::draw(NVGcontext *ctx) { 56 | Widget::draw(ctx); 57 | nvgFontFace(ctx, mFont.c_str()); 58 | nvgFontSize(ctx, fontSize()); 59 | nvgFillColor(ctx, mColor); 60 | if (mFixedSize.x() > 0) { 61 | nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); 62 | nvgTextBox(ctx, mPos.x(), mPos.y(), mFixedSize.x(), mCaption.c_str(), nullptr); 63 | } else { 64 | nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); 65 | nvgText(ctx, mPos.x(), mPos.y() + mSize.y() * 0.5f, mCaption.c_str(), nullptr); 66 | } 67 | } 68 | 69 | void Label::save(Serializer &s) const { 70 | Widget::save(s); 71 | s.set("caption", mCaption); 72 | s.set("font", mFont); 73 | s.set("color", mColor); 74 | } 75 | 76 | bool Label::load(Serializer &s) { 77 | if (!Widget::load(s)) return false; 78 | if (!s.get("caption", mCaption)) return false; 79 | if (!s.get("font", mFont)) return false; 80 | if (!s.get("color", mColor)) return false; 81 | return true; 82 | } 83 | 84 | NAMESPACE_END(nanogui) 85 | -------------------------------------------------------------------------------- /src/messagedialog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/messagedialog.cpp -- Simple "OK" or "Yes/No"-style modal dialogs 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | MessageDialog::MessageDialog(Widget *parent, Type type, const std::string &title, 20 | const std::string &message, 21 | const std::string &buttonText, 22 | const std::string &altButtonText, bool altButton) : Window(parent, title) { 23 | setLayout(new BoxLayout(Orientation::Vertical, 24 | Alignment::Middle, 10, 10)); 25 | setModal(true); 26 | 27 | Widget *panel1 = new Widget(this); 28 | panel1->setLayout(new BoxLayout(Orientation::Horizontal, 29 | Alignment::Middle, 10, 15)); 30 | int icon = 0; 31 | switch (type) { 32 | case Type::Information: icon = mTheme->mMessageInformationIcon; break; 33 | case Type::Question: icon = mTheme->mMessageQuestionIcon; break; 34 | case Type::Warning: icon = mTheme->mMessageWarningIcon; break; 35 | } 36 | Label *iconLabel = new Label(panel1, std::string(utf8(icon).data()), "icons"); 37 | iconLabel->setFontSize(50); 38 | mMessageLabel = new Label(panel1, message); 39 | mMessageLabel->setFixedWidth(200); 40 | Widget *panel2 = new Widget(this); 41 | panel2->setLayout(new BoxLayout(Orientation::Horizontal, 42 | Alignment::Middle, 0, 15)); 43 | 44 | if (altButton) { 45 | Button *button = new Button(panel2, altButtonText, mTheme->mMessageAltButtonIcon); 46 | button->setCallback([&] { if (mCallback) mCallback(1); dispose(); }); 47 | } 48 | Button *button = new Button(panel2, buttonText, mTheme->mMessagePrimaryButtonIcon); 49 | button->setCallback([&] { if (mCallback) mCallback(0); dispose(); }); 50 | center(); 51 | requestFocus(); 52 | } 53 | 54 | NAMESPACE_END(nanogui) 55 | -------------------------------------------------------------------------------- /src/popup.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/popup.cpp -- Simple popup widget which is attached to another given 3 | window (can be nested) 4 | 5 | NanoGUI was developed by Wenzel Jakob . 6 | The widget drawing code is based on the NanoVG demo application 7 | by Mikko Mononen. 8 | 9 | All rights reserved. Use of this source code is governed by a 10 | BSD-style license that can be found in the LICENSE.txt file. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | NAMESPACE_BEGIN(nanogui) 19 | 20 | Popup::Popup(Widget *parent, Window *parentWindow) 21 | : Window(parent, ""), mParentWindow(parentWindow), 22 | mAnchorPos(Vector2i::Zero()), mAnchorHeight(30), mSide(Side::Right) { 23 | } 24 | 25 | void Popup::performLayout(NVGcontext *ctx) { 26 | if (mLayout || mChildren.size() != 1) { 27 | Widget::performLayout(ctx); 28 | } else { 29 | mChildren[0]->setPosition(Vector2i::Zero()); 30 | mChildren[0]->setSize(mSize); 31 | mChildren[0]->performLayout(ctx); 32 | } 33 | if (mSide == Side::Left) 34 | mAnchorPos[0] -= size()[0]; 35 | } 36 | 37 | void Popup::refreshRelativePlacement() { 38 | mParentWindow->refreshRelativePlacement(); 39 | mVisible &= mParentWindow->visibleRecursive(); 40 | mPos = mParentWindow->position() + mAnchorPos - Vector2i(0, mAnchorHeight); 41 | } 42 | 43 | void Popup::draw(NVGcontext* ctx) { 44 | refreshRelativePlacement(); 45 | 46 | if (!mVisible) 47 | return; 48 | 49 | int ds = mTheme->mWindowDropShadowSize, cr = mTheme->mWindowCornerRadius; 50 | 51 | nvgSave(ctx); 52 | nvgResetScissor(ctx); 53 | 54 | /* Draw a drop shadow */ 55 | NVGpaint shadowPaint = nvgBoxGradient( 56 | ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), cr*2, ds*2, 57 | mTheme->mDropShadow, mTheme->mTransparent); 58 | 59 | nvgBeginPath(ctx); 60 | nvgRect(ctx, mPos.x()-ds,mPos.y()-ds, mSize.x()+2*ds, mSize.y()+2*ds); 61 | nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), cr); 62 | nvgPathWinding(ctx, NVG_HOLE); 63 | nvgFillPaint(ctx, shadowPaint); 64 | nvgFill(ctx); 65 | 66 | /* Draw window */ 67 | nvgBeginPath(ctx); 68 | nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), cr); 69 | 70 | Vector2i base = mPos + Vector2i(0, mAnchorHeight); 71 | int sign = -1; 72 | if (mSide == Side::Left) { 73 | base.x() += mSize.x(); 74 | sign = 1; 75 | } 76 | 77 | nvgMoveTo(ctx, base.x() + 15*sign, base.y()); 78 | nvgLineTo(ctx, base.x() - 1*sign, base.y() - 15); 79 | nvgLineTo(ctx, base.x() - 1*sign, base.y() + 15); 80 | 81 | nvgFillColor(ctx, mTheme->mWindowPopup); 82 | nvgFill(ctx); 83 | nvgRestore(ctx); 84 | 85 | Widget::draw(ctx); 86 | } 87 | 88 | void Popup::save(Serializer &s) const { 89 | Window::save(s); 90 | s.set("anchorPos", mAnchorPos); 91 | s.set("anchorHeight", mAnchorHeight); 92 | s.set("side", mSide); 93 | } 94 | 95 | bool Popup::load(Serializer &s) { 96 | if (!Window::load(s)) return false; 97 | if (!s.get("anchorPos", mAnchorPos)) return false; 98 | if (!s.get("anchorHeight", mAnchorHeight)) return false; 99 | if (!s.get("side", mSide)) return false; 100 | return true; 101 | } 102 | 103 | NAMESPACE_END(nanogui) 104 | -------------------------------------------------------------------------------- /src/popupbutton.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/popupbutton.cpp -- Button which launches a popup widget 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | PopupButton::PopupButton(Widget *parent, const std::string &caption, int buttonIcon) 20 | : Button(parent, caption, buttonIcon) { 21 | 22 | mChevronIcon = mTheme->mPopupChevronRightIcon; 23 | 24 | setFlags(Flags::ToggleButton | Flags::PopupButton); 25 | 26 | Window *parentWindow = window(); 27 | mPopup = new Popup(parentWindow->parent(), window()); 28 | mPopup->setSize(Vector2i(320, 250)); 29 | mPopup->setVisible(false); 30 | 31 | mIconExtraScale = 0.8f;// widget override 32 | } 33 | 34 | PopupButton::~PopupButton() { 35 | mPopup->setVisible(false); 36 | } 37 | 38 | Vector2i PopupButton::preferredSize(NVGcontext *ctx) const { 39 | return Button::preferredSize(ctx) + Vector2i(15, 0); 40 | } 41 | 42 | void PopupButton::draw(NVGcontext* ctx) { 43 | if (!mEnabled && mPushed) 44 | mPushed = false; 45 | 46 | mPopup->setVisible(mPushed); 47 | Button::draw(ctx); 48 | 49 | if (mChevronIcon) { 50 | auto icon = utf8(mChevronIcon); 51 | NVGcolor textColor = 52 | mTextColor.w() == 0 ? mTheme->mTextColor : mTextColor; 53 | 54 | nvgFontSize(ctx, (mFontSize < 0 ? mTheme->mButtonFontSize : mFontSize) * icon_scale()); 55 | nvgFontFace(ctx, "icons"); 56 | nvgFillColor(ctx, mEnabled ? textColor : mTheme->mDisabledTextColor); 57 | nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); 58 | 59 | float iw = nvgTextBounds(ctx, 0, 0, icon.data(), nullptr, nullptr); 60 | Vector2f iconPos(0, mPos.y() + mSize.y() * 0.5f - 1); 61 | 62 | if (mPopup->side() == Popup::Right) 63 | iconPos[0] = mPos.x() + mSize.x() - iw - 8; 64 | else 65 | iconPos[0] = mPos.x() + 8; 66 | 67 | nvgText(ctx, iconPos.x(), iconPos.y(), icon.data(), nullptr); 68 | } 69 | } 70 | 71 | void PopupButton::performLayout(NVGcontext *ctx) { 72 | Widget::performLayout(ctx); 73 | 74 | const Window *parentWindow = window(); 75 | 76 | int posY = absolutePosition().y() - parentWindow->position().y() + mSize.y() /2; 77 | if (mPopup->side() == Popup::Right) 78 | mPopup->setAnchorPos(Vector2i(parentWindow->width() + 15, posY)); 79 | else 80 | mPopup->setAnchorPos(Vector2i(0 - 15, posY)); 81 | } 82 | 83 | void PopupButton::setSide(Popup::Side side) { 84 | if (mPopup->side() == Popup::Right && 85 | mChevronIcon == mTheme->mPopupChevronRightIcon) 86 | setChevronIcon(mTheme->mPopupChevronLeftIcon); 87 | else if (mPopup->side() == Popup::Left && 88 | mChevronIcon == mTheme->mPopupChevronLeftIcon) 89 | setChevronIcon(mTheme->mPopupChevronRightIcon); 90 | mPopup->setSide(side); 91 | } 92 | 93 | void PopupButton::save(Serializer &s) const { 94 | Button::save(s); 95 | s.set("chevronIcon", mChevronIcon); 96 | } 97 | 98 | bool PopupButton::load(Serializer &s) { 99 | if (!Button::load(s)) 100 | return false; 101 | if (!s.get("chevronIcon", mChevronIcon)) 102 | return false; 103 | return true; 104 | } 105 | 106 | NAMESPACE_END(nanogui) 107 | -------------------------------------------------------------------------------- /src/progressbar.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/progressbar.cpp -- Standard widget for visualizing progress 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | NAMESPACE_BEGIN(nanogui) 17 | 18 | ProgressBar::ProgressBar(Widget *parent) 19 | : Widget(parent), mValue(0.0f) {} 20 | 21 | Vector2i ProgressBar::preferredSize(NVGcontext *) const { 22 | return Vector2i(70, 12); 23 | } 24 | 25 | void ProgressBar::draw(NVGcontext* ctx) { 26 | Widget::draw(ctx); 27 | 28 | NVGpaint paint = nvgBoxGradient( 29 | ctx, mPos.x() + 1, mPos.y() + 1, 30 | mSize.x()-2, mSize.y(), 3, 4, Color(0, 32), Color(0, 92)); 31 | nvgBeginPath(ctx); 32 | nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), 3); 33 | nvgFillPaint(ctx, paint); 34 | nvgFill(ctx); 35 | 36 | float value = std::min(std::max(0.0f, mValue), 1.0f); 37 | int barPos = (int) std::round((mSize.x() - 2) * value); 38 | 39 | paint = nvgBoxGradient( 40 | ctx, mPos.x(), mPos.y(), 41 | barPos+1.5f, mSize.y()-1, 3, 4, 42 | Color(220, 100), Color(128, 100)); 43 | 44 | nvgBeginPath(ctx); 45 | nvgRoundedRect( 46 | ctx, mPos.x()+1, mPos.y()+1, 47 | barPos, mSize.y()-2, 3); 48 | nvgFillPaint(ctx, paint); 49 | nvgFill(ctx); 50 | } 51 | 52 | void ProgressBar::save(Serializer &s) const { 53 | Widget::save(s); 54 | s.set("value", mValue); 55 | } 56 | 57 | bool ProgressBar::load(Serializer &s) { 58 | if (!Widget::load(s)) 59 | return false; 60 | if (!s.get("value", mValue)) 61 | return false; 62 | return true; 63 | } 64 | 65 | NAMESPACE_END(nanogui) 66 | -------------------------------------------------------------------------------- /src/slider.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/slider.cpp -- Fractional slider widget with mouse control 3 | 4 | NanoGUI was developed by Wenzel Jakob . 5 | The widget drawing code is based on the NanoVG demo application 6 | by Mikko Mononen. 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE.txt file. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | Slider::Slider(Widget *parent) 20 | : Widget(parent), mValue(0.0f), mRange(0.f, 1.f), 21 | mHighlightedRange(0.f, 0.f) { 22 | mHighlightColor = Color(255, 80, 80, 70); 23 | } 24 | 25 | Vector2i Slider::preferredSize(NVGcontext *) const { 26 | return Vector2i(70, 16); 27 | } 28 | 29 | bool Slider::mouseDragEvent(const Vector2i &p, const Vector2i & /* rel */, 30 | int /* button */, int /* modifiers */) { 31 | if (!mEnabled) 32 | return false; 33 | 34 | const float kr = (int) (mSize.y() * 0.4f), kshadow = 3; 35 | const float startX = kr + kshadow + mPos.x() - 1; 36 | const float widthX = mSize.x() - 2 * (kr + kshadow); 37 | 38 | float value = (p.x() - startX) / widthX; 39 | value = value * (mRange.second - mRange.first) + mRange.first; 40 | mValue = std::min(std::max(value, mRange.first), mRange.second); 41 | if (mCallback) 42 | mCallback(mValue); 43 | return true; 44 | } 45 | 46 | bool Slider::mouseButtonEvent(const Vector2i &p, int /* button */, bool down, int /* modifiers */) { 47 | if (!mEnabled) 48 | return false; 49 | 50 | const float kr = (int) (mSize.y() * 0.4f), kshadow = 3; 51 | const float startX = kr + kshadow + mPos.x() - 1; 52 | const float widthX = mSize.x() - 2 * (kr + kshadow); 53 | 54 | float value = (p.x() - startX) / widthX; 55 | value = value * (mRange.second - mRange.first) + mRange.first; 56 | mValue = std::min(std::max(value, mRange.first), mRange.second); 57 | if (mCallback) 58 | mCallback(mValue); 59 | if (mFinalCallback && !down) 60 | mFinalCallback(mValue); 61 | return true; 62 | } 63 | 64 | void Slider::draw(NVGcontext* ctx) { 65 | Vector2f center = mPos.cast() + mSize.cast() * 0.5f; 66 | float kr = (int) (mSize.y() * 0.4f), kshadow = 3; 67 | 68 | float startX = kr + kshadow + mPos.x(); 69 | float widthX = mSize.x() - 2*(kr+kshadow); 70 | 71 | Vector2f knobPos(startX + (mValue - mRange.first) / 72 | (mRange.second - mRange.first) * widthX, 73 | center.y() + 0.5f); 74 | 75 | NVGpaint bg = nvgBoxGradient( 76 | ctx, startX, center.y() - 3 + 1, widthX, 6, 3, 3, 77 | Color(0, mEnabled ? 32 : 10), Color(0, mEnabled ? 128 : 210)); 78 | 79 | nvgBeginPath(ctx); 80 | nvgRoundedRect(ctx, startX, center.y() - 3 + 1, widthX, 6, 2); 81 | nvgFillPaint(ctx, bg); 82 | nvgFill(ctx); 83 | 84 | if (mHighlightedRange.second != mHighlightedRange.first) { 85 | nvgBeginPath(ctx); 86 | nvgRoundedRect(ctx, startX + mHighlightedRange.first * mSize.x(), 87 | center.y() - kshadow + 1, 88 | widthX * 89 | (mHighlightedRange.second - mHighlightedRange.first), 90 | kshadow * 2, 2); 91 | nvgFillColor(ctx, mHighlightColor); 92 | nvgFill(ctx); 93 | } 94 | 95 | NVGpaint knobShadow = 96 | nvgRadialGradient(ctx, knobPos.x(), knobPos.y(), kr - kshadow, 97 | kr + kshadow, Color(0, 64), mTheme->mTransparent); 98 | 99 | nvgBeginPath(ctx); 100 | nvgRect(ctx, knobPos.x() - kr - 5, knobPos.y() - kr - 5, kr * 2 + 10, 101 | kr * 2 + 10 + kshadow); 102 | nvgCircle(ctx, knobPos.x(), knobPos.y(), kr); 103 | nvgPathWinding(ctx, NVG_HOLE); 104 | nvgFillPaint(ctx, knobShadow); 105 | nvgFill(ctx); 106 | 107 | NVGpaint knob = nvgLinearGradient(ctx, 108 | mPos.x(), center.y() - kr, mPos.x(), center.y() + kr, 109 | mTheme->mBorderLight, mTheme->mBorderMedium); 110 | NVGpaint knobReverse = nvgLinearGradient(ctx, 111 | mPos.x(), center.y() - kr, mPos.x(), center.y() + kr, 112 | mTheme->mBorderMedium, 113 | mTheme->mBorderLight); 114 | 115 | nvgBeginPath(ctx); 116 | nvgCircle(ctx, knobPos.x(), knobPos.y(), kr); 117 | nvgStrokeColor(ctx, mTheme->mBorderDark); 118 | nvgFillPaint(ctx, knob); 119 | nvgStroke(ctx); 120 | nvgFill(ctx); 121 | nvgBeginPath(ctx); 122 | nvgCircle(ctx, knobPos.x(), knobPos.y(), kr/2); 123 | nvgFillColor(ctx, Color(150, mEnabled ? 255 : 100)); 124 | nvgStrokePaint(ctx, knobReverse); 125 | nvgStroke(ctx); 126 | nvgFill(ctx); 127 | } 128 | 129 | void Slider::save(Serializer &s) const { 130 | Widget::save(s); 131 | s.set("value", mValue); 132 | s.set("range", mRange); 133 | s.set("highlightedRange", mHighlightedRange); 134 | s.set("highlightColor", mHighlightColor); 135 | } 136 | 137 | bool Slider::load(Serializer &s) { 138 | if (!Widget::load(s)) return false; 139 | if (!s.get("value", mValue)) return false; 140 | if (!s.get("range", mRange)) return false; 141 | if (!s.get("highlightedRange", mHighlightedRange)) return false; 142 | if (!s.get("highlightColor", mHighlightColor)) return false; 143 | return true; 144 | } 145 | 146 | NAMESPACE_END(nanogui) 147 | -------------------------------------------------------------------------------- /src/stackedwidget.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | nanogui/stackedwidget.cpp -- Widget used to stack widgets on top 3 | of each other. Only the active widget is visible. 4 | 5 | The stacked widget was contributed by Stefan Ivanov. 6 | 7 | NanoGUI was developed by Wenzel Jakob . 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 16 | 17 | NAMESPACE_BEGIN(nanogui) 18 | 19 | StackedWidget::StackedWidget(nanogui::Widget *parent) 20 | : Widget(parent) { } 21 | 22 | void StackedWidget::setSelectedIndex(int index) { 23 | assert(index < childCount()); 24 | if (mSelectedIndex >= 0) 25 | mChildren[mSelectedIndex]->setVisible(false); 26 | mSelectedIndex = index; 27 | mChildren[mSelectedIndex]->setVisible(true); 28 | } 29 | 30 | int StackedWidget::selectedIndex() const { 31 | return mSelectedIndex; 32 | } 33 | 34 | void StackedWidget::performLayout(NVGcontext *ctx) { 35 | for (auto child : mChildren) { 36 | child->setPosition(Vector2i::Zero()); 37 | child->setSize(mSize); 38 | child->performLayout(ctx); 39 | } 40 | } 41 | 42 | Vector2i StackedWidget::preferredSize(NVGcontext *ctx) const { 43 | Vector2i size = Vector2i::Zero(); 44 | for (auto child : mChildren) 45 | size = size.cwiseMax(child->preferredSize(ctx)); 46 | return size; 47 | } 48 | 49 | void StackedWidget::addChild(int index, Widget *widget) { 50 | if (mSelectedIndex >= 0) 51 | mChildren[mSelectedIndex]->setVisible(false); 52 | Widget::addChild(index, widget); 53 | widget->setVisible(true); 54 | setSelectedIndex(index); 55 | } 56 | 57 | NAMESPACE_END(nanogui) 58 | -------------------------------------------------------------------------------- /src/theme.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/theme.cpp -- Storage class for basic theme-related properties 3 | 4 | The text box widget was contributed by Christian Schueller. 5 | 6 | NanoGUI was developed by Wenzel Jakob . 7 | The widget drawing code is based on the NanoVG demo application 8 | by Mikko Mononen. 9 | 10 | All rights reserved. Use of this source code is governed by a 11 | BSD-style license that can be found in the LICENSE.txt file. 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | NAMESPACE_BEGIN(nanogui) 20 | 21 | Theme::Theme(NVGcontext *ctx) { 22 | mStandardFontSize = 16; 23 | mButtonFontSize = 20; 24 | mTextBoxFontSize = 20; 25 | mIconScale = 0.77f; 26 | 27 | mWindowCornerRadius = 2; 28 | mWindowHeaderHeight = 30; 29 | mWindowDropShadowSize = 10; 30 | mButtonCornerRadius = 2; 31 | mTabBorderWidth = 0.75f; 32 | mTabInnerMargin = 5; 33 | mTabMinButtonWidth = 20; 34 | mTabMaxButtonWidth = 160; 35 | mTabControlWidth = 20; 36 | mTabButtonHorizontalPadding = 10; 37 | mTabButtonVerticalPadding = 2; 38 | 39 | mDropShadow = Color(0, 128); 40 | mTransparent = Color(0, 0); 41 | mBorderDark = Color(29, 255); 42 | mBorderLight = Color(92, 255); 43 | mBorderMedium = Color(35, 255); 44 | mTextColor = Color(255, 160); 45 | mDisabledTextColor = Color(255, 80); 46 | mTextColorShadow = Color(0, 160); 47 | mIconColor = mTextColor; 48 | 49 | mButtonGradientTopFocused = Color(64, 255); 50 | mButtonGradientBotFocused = Color(48, 255); 51 | mButtonGradientTopUnfocused = Color(74, 255); 52 | mButtonGradientBotUnfocused = Color(58, 255); 53 | mButtonGradientTopPushed = Color(41, 255); 54 | mButtonGradientBotPushed = Color(29, 255); 55 | 56 | /* Window-related */ 57 | mWindowFillUnfocused = Color(43, 230); 58 | mWindowFillFocused = Color(45, 230); 59 | mWindowTitleUnfocused = Color(220, 160); 60 | mWindowTitleFocused = Color(255, 190); 61 | 62 | mWindowHeaderGradientTop = mButtonGradientTopUnfocused; 63 | mWindowHeaderGradientBot = mButtonGradientBotUnfocused; 64 | mWindowHeaderSepTop = mBorderLight; 65 | mWindowHeaderSepBot = mBorderDark; 66 | 67 | mWindowPopup = Color(50, 255); 68 | mWindowPopupTransparent = Color(50, 0); 69 | 70 | mCheckBoxIcon = ENTYPO_ICON_CHECK; 71 | mMessageInformationIcon = ENTYPO_ICON_INFO_WITH_CIRCLE; 72 | mMessageQuestionIcon = ENTYPO_ICON_HELP_WITH_CIRCLE; 73 | mMessageWarningIcon = ENTYPO_ICON_WARNING; 74 | mMessageAltButtonIcon = ENTYPO_ICON_CIRCLE_WITH_CROSS; 75 | mMessagePrimaryButtonIcon = ENTYPO_ICON_CHECK; 76 | mPopupChevronRightIcon = ENTYPO_ICON_CHEVRON_RIGHT; 77 | mPopupChevronLeftIcon = ENTYPO_ICON_CHEVRON_LEFT; 78 | mTabHeaderLeftIcon = ENTYPO_ICON_ARROW_BOLD_LEFT; 79 | mTabHeaderRightIcon = ENTYPO_ICON_ARROW_BOLD_RIGHT; 80 | mTextBoxUpIcon = ENTYPO_ICON_CHEVRON_UP; 81 | mTextBoxDownIcon = ENTYPO_ICON_CHEVRON_DOWN; 82 | 83 | mFontNormal = nvgCreateFontMem(ctx, "sans", roboto_regular_ttf, 84 | roboto_regular_ttf_size, 0); 85 | mFontBold = nvgCreateFontMem(ctx, "sans-bold", roboto_bold_ttf, 86 | roboto_bold_ttf_size, 0); 87 | mFontIcons = nvgCreateFontMem(ctx, "icons", entypo_ttf, 88 | entypo_ttf_size, 0); 89 | if (mFontNormal == -1 || mFontBold == -1 || mFontIcons == -1) 90 | throw std::runtime_error("Could not load fonts!"); 91 | } 92 | 93 | NAMESPACE_END(nanogui) 94 | -------------------------------------------------------------------------------- /src/vscrollpanel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | src/vscrollpanel.cpp -- Adds a vertical scrollbar around a widget 3 | that is too big to fit into a certain area 4 | 5 | NanoGUI was developed by Wenzel Jakob . 6 | The widget drawing code is based on the NanoVG demo application 7 | by Mikko Mononen. 8 | 9 | All rights reserved. Use of this source code is governed by a 10 | BSD-style license that can be found in the LICENSE.txt file. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | NAMESPACE_BEGIN(nanogui) 19 | 20 | VScrollPanel::VScrollPanel(Widget *parent) 21 | : Widget(parent), mChildPreferredHeight(0), mScroll(0.0f), mUpdateLayout(false) { } 22 | 23 | void VScrollPanel::performLayout(NVGcontext *ctx) { 24 | Widget::performLayout(ctx); 25 | 26 | if (mChildren.empty()) 27 | return; 28 | if (mChildren.size() > 1) 29 | throw std::runtime_error("VScrollPanel should have one child."); 30 | 31 | Widget *child = mChildren[0]; 32 | mChildPreferredHeight = child->preferredSize(ctx).y(); 33 | 34 | if (mChildPreferredHeight > mSize.y()) { 35 | child->setPosition(Vector2i(0, -mScroll*(mChildPreferredHeight - mSize.y()))); 36 | child->setSize(Vector2i(mSize.x()-12, mChildPreferredHeight)); 37 | } else { 38 | child->setPosition(Vector2i::Zero()); 39 | child->setSize(mSize); 40 | mScroll = 0; 41 | } 42 | child->performLayout(ctx); 43 | } 44 | 45 | Vector2i VScrollPanel::preferredSize(NVGcontext *ctx) const { 46 | if (mChildren.empty()) 47 | return Vector2i::Zero(); 48 | return mChildren[0]->preferredSize(ctx) + Vector2i(12, 0); 49 | } 50 | 51 | bool VScrollPanel::mouseDragEvent(const Vector2i &p, const Vector2i &rel, 52 | int button, int modifiers) { 53 | if (!mChildren.empty() && mChildPreferredHeight > mSize.y()) { 54 | float scrollh = height() * 55 | std::min(1.0f, height() / (float)mChildPreferredHeight); 56 | 57 | mScroll = std::max((float) 0.0f, std::min((float) 1.0f, 58 | mScroll + rel.y() / (float)(mSize.y() - 8 - scrollh))); 59 | mUpdateLayout = true; 60 | return true; 61 | } else { 62 | return Widget::mouseDragEvent(p, rel, button, modifiers); 63 | } 64 | } 65 | 66 | bool VScrollPanel::scrollEvent(const Vector2i &p, const Vector2f &rel) { 67 | if (!mChildren.empty() && mChildPreferredHeight > mSize.y()) { 68 | float scrollAmount = rel.y() * (mSize.y() / 20.0f); 69 | float scrollh = height() * 70 | std::min(1.0f, height() / (float)mChildPreferredHeight); 71 | 72 | mScroll = std::max((float) 0.0f, std::min((float) 1.0f, 73 | mScroll - scrollAmount / (float)(mSize.y() - 8 - scrollh))); 74 | mUpdateLayout = true; 75 | return true; 76 | } else { 77 | return Widget::scrollEvent(p, rel); 78 | } 79 | } 80 | 81 | void VScrollPanel::draw(NVGcontext *ctx) { 82 | if (mChildren.empty()) 83 | return; 84 | Widget *child = mChildren[0]; 85 | child->setPosition(Vector2i(0, -mScroll*(mChildPreferredHeight - mSize.y()))); 86 | mChildPreferredHeight = child->preferredSize(ctx).y(); 87 | float scrollh = height() * 88 | std::min(1.0f, height() / (float) mChildPreferredHeight); 89 | 90 | if (mUpdateLayout) 91 | child->performLayout(ctx); 92 | 93 | nvgSave(ctx); 94 | nvgTranslate(ctx, mPos.x(), mPos.y()); 95 | nvgIntersectScissor(ctx, 0, 0, mSize.x(), mSize.y()); 96 | if (child->visible()) 97 | child->draw(ctx); 98 | nvgRestore(ctx); 99 | 100 | if (mChildPreferredHeight <= mSize.y()) 101 | return; 102 | 103 | NVGpaint paint = nvgBoxGradient( 104 | ctx, mPos.x() + mSize.x() - 12 + 1, mPos.y() + 4 + 1, 8, 105 | mSize.y() - 8, 3, 4, Color(0, 32), Color(0, 92)); 106 | nvgBeginPath(ctx); 107 | nvgRoundedRect(ctx, mPos.x() + mSize.x() - 12, mPos.y() + 4, 8, 108 | mSize.y() - 8, 3); 109 | nvgFillPaint(ctx, paint); 110 | nvgFill(ctx); 111 | 112 | paint = nvgBoxGradient( 113 | ctx, mPos.x() + mSize.x() - 12 - 1, 114 | mPos.y() + 4 + (mSize.y() - 8 - scrollh) * mScroll - 1, 8, scrollh, 115 | 3, 4, Color(220, 100), Color(128, 100)); 116 | 117 | nvgBeginPath(ctx); 118 | nvgRoundedRect(ctx, mPos.x() + mSize.x() - 12 + 1, 119 | mPos.y() + 4 + 1 + (mSize.y() - 8 - scrollh) * mScroll, 8 - 2, 120 | scrollh - 2, 2); 121 | nvgFillPaint(ctx, paint); 122 | nvgFill(ctx); 123 | } 124 | 125 | void VScrollPanel::save(Serializer &s) const { 126 | Widget::save(s); 127 | s.set("childPreferredHeight", mChildPreferredHeight); 128 | s.set("scroll", mScroll); 129 | } 130 | 131 | bool VScrollPanel::load(Serializer &s) { 132 | if (!Widget::load(s)) return false; 133 | if (!s.get("childPreferredHeight", mChildPreferredHeight)) return false; 134 | if (!s.get("scroll", mScroll)) return false; 135 | return true; 136 | } 137 | 138 | NAMESPACE_END(nanogui) 139 | --------------------------------------------------------------------------------