/* src/example1.cpp -- C++ version of an example application that shows how to use the various widget classes. For a Python implementation, see '../python/example1.py'. NanoGUI was developed by Wenzel Jakob . The widget drawing code is based on the NanoVG demo application by Mikko Mononen. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE.txt file. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Includes for the GLTexture class. #include #include #include #if defined(__GNUC__) # pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif #if defined(_WIN32) # pragma warning(push) # pragma warning(disable: 4457 4456 4005 4312) #endif #define STB_IMAGE_IMPLEMENTATION #include #if defined(_WIN32) # pragma warning(pop) #endif #if defined(_WIN32) # if defined(APIENTRY) # undef APIENTRY # endif # include #endif using std::cout; using std::cerr; using std::endl; using std::string; using std::vector; using std::pair; using std::to_string; class GLTexture { public: using handleType = std::unique_ptr; GLTexture() = default; GLTexture(const std::string& textureName) : mTextureName(textureName), mTextureId(0) {} GLTexture(const std::string& textureName, GLint textureId) : mTextureName(textureName), mTextureId(textureId) {} GLTexture(const GLTexture& other) = delete; GLTexture(GLTexture&& other) noexcept : mTextureName(std::move(other.mTextureName)), mTextureId(other.mTextureId) { other.mTextureId = 0; } GLTexture& operator=(const GLTexture& other) = delete; GLTexture& operator=(GLTexture&& other) noexcept { mTextureName = std::move(other.mTextureName); std::swap(mTextureId, other.mTextureId); return *this; } ~GLTexture() noexcept { if (mTextureId) glDeleteTextures(1, &mTextureId); } GLuint texture() const { return mTextureId; } const std::string& textureName() const { return mTextureName; } /** * Load a file in memory and create an OpenGL texture. * Returns a handle type (an std::unique_ptr) to the loaded pixels. */ handleType load(const std::string& fileName) { if (mTextureId) { glDeleteTextures(1, &mTextureId); mTextureId = 0; } int force_channels = 0; int w, h, n; handleType textureData(stbi_load(fileName.c_str(), &w, &h, &n, force_channels), stbi_image_free); if (!textureData) throw std::invalid_argument("Could not load texture data from file " + fileName); glGenTextures(1, &mTextureId); glBindTexture(GL_TEXTURE_2D, mTextureId); GLint internalFormat; GLint format; switch (n) { case 1: internalFormat = GL_R8; format = GL_RED; break; case 2: internalFormat = GL_RG8; format = GL_RG; break; case 3: internalFormat = GL_RGB8; format = GL_RGB; break; case 4: internalFormat = GL_RGBA8; format = GL_RGBA; break; default: internalFormat = 0; format = 0; break; } glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_BYTE, textureData.get()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); return textureData; } private: std::string mTextureName; GLuint mTextureId; }; class ExampleApplication : public nanogui::Screen { public: ExampleApplication() : nanogui::Screen(Eigen::Vector2i(1024, 768), "NanoGUI Test") { using namespace nanogui; Window *window = new Window(this, "Button demo"); window->setPosition(Vector2i(15, 15)); window->setLayout(new GroupLayout()); /* No need to store a pointer, the data structure will be automatically freed when the parent window is deleted */ new Label(window, "Push buttons", "sans-bold"); Button *b = new Button(window, "Plain button"); b->setCallback([] { cout << "pushed!" << endl; }); b->setTooltip("short tooltip"); /* Alternative construction notation using variadic template */ b = window->add