├── LICENSE ├── README.md ├── assimp ├── CMakeLists.txt ├── README.md ├── cmake │ └── Modules │ │ ├── DownloadProject.CMakeLists.cmake.in │ │ └── DownloadProject.cmake └── src │ └── Sample_SimpleOpenGL.c ├── imgui ├── CMakeLists.txt ├── README.md ├── include │ ├── imgui_impl_glfw.h │ └── imgui_impl_sdl.h ├── libs │ └── imgui │ │ ├── CMakeLists.txt │ │ ├── LICENSE.txt │ │ ├── imgui.cpp │ │ ├── imgui_demo.cpp │ │ ├── imgui_draw.cpp │ │ └── include │ │ ├── imconfig.h │ │ ├── imgui.h │ │ ├── imgui_internal.h │ │ ├── stb_rect_pack.h │ │ ├── stb_textedit.h │ │ └── stb_truetype.h └── src │ ├── imgui_impl_glfw.cpp │ ├── imgui_impl_sdl.cpp │ ├── main.cpp │ └── main_sdl.cpp ├── minizip ├── CMakeLists.txt ├── README.md └── src │ ├── miniunzip.c │ └── minizip.c ├── nanovg ├── CMakeLists.txt ├── README.md ├── libs │ └── nanovg │ │ ├── CMakeLists.txt │ │ ├── LICENSE.txt │ │ ├── README.md │ │ ├── premake4.lua │ │ └── src │ │ ├── fontstash.h │ │ ├── nanovg.c │ │ ├── nanovg.h │ │ ├── nanovg_gl.h │ │ ├── nanovg_gl_utils.h │ │ ├── stb_image.h │ │ └── stb_truetype.h ├── media │ ├── LICENSE │ └── NotoSansUI-Regular.ttf └── src │ └── torus.cpp └── zmq ├── CMakeLists.txt ├── README.md ├── cmake └── Modules │ ├── FindZeroMQ-LICENSE.txt │ ├── FindZeroMQ.cmake │ └── README.txt ├── include ├── config.h └── zhelpers.h └── src ├── config.c ├── version.c ├── wuclient.c └── wuserver.c /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | Copyright (c) 2018 Scott Francis 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 4 | associated documentation files (the "Software"), to deal in the Software without restriction, 5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 7 | subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 13 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 14 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 16 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CMake Cookbook 2 | This is a collection of subprojects showing various advanced facets of [CMake](https://cmake.org). It started out as a personal tool-evaluation repository for graphic and networking libraries, and shows some of the ways I use CMake. 3 | 4 | The "source" files being compiled in these examples are taken directly from the project being shown. Only CMake is on display here. 5 | 6 | If you've never used CMake before, please see [A Brief Beginner's Guide to CMake](https://github.com/pyk/cmake-tutorial), which served as inspiration for releasing this repository. 7 | 8 | ## Use 9 | Each project has a README detailing sub-requirements, showing the project layout, and walking through the CMakeLists.txt files. 10 | 11 | Generally to build each, the following usage is encouraged: 12 | ``` 13 | $ mkdir build 14 | $ cd build 15 | $ cmake .. 16 | $ 17 | ``` 18 | 19 | This is what's known as an "out-of-source" build, and it is strongly encouraged with CMake. There are a few major advantages in CMake: 20 | - There will be a LOT of files generated, and it's easier to have a `build/*` directive in your SCM ignore file, versus manually cleaning out after a build. 21 | - when creating/debugging a CMakeLists.txt file, it's easy to remove the directory and not have to worry about any lingering CMake variables hiding in CMakeCache.txt or other locations. Subsequent `cmake`/`make` calls will NOT remove variables you might have set in previous versions of your CMakeLists.txt! 22 | - it's easy to search through the directory to find out what a 3rd-party library is trying to do while debugging a CMakeLists.txt file 23 | 24 | Don't forget there are many ways of running CMake beyond the standard CLI invocation! See the official [Running CMake](https://cmake.org/runningcmake/) page for more. 25 | 26 | ## Tested Platforms 27 | - OpenBSD 6.2 28 | - OSX 10.11 w/ Macports 2.4.2 29 | - Debian stretch 30 | 31 | There should be no issues with running these examples on Windows, but no testing has been performed due to lack of access to a Windows system. 32 | 33 | ## Requirements: 34 | ### Linux: 35 | - build-essential 36 | - git 37 | - cmake 38 | - pkg-config 39 | 40 | ### OSX/BSD: 41 | - git 42 | - cmake 43 | - pkg-config 44 | 45 | ## Licensing 46 | The base CMakeLists.txt and README.md files in each directory were created for the cmake_cookbook project, and are covered under the terms of the MIT License detailed in the LICENSE file. 47 | 48 | The CMakeLists.txt files in nanovg/libs/nanovg/ and imgui/libs/imgui were also created for the cmake_cookbook, and are also covered under the MIT License. 49 | 50 | Code samples in the src/ directories are taken from the projects being shown and should be considered to be under the license for that specific project. 51 | 52 | In the interest of having a working example for nanovg, the nanovg/media directory contains a copy of the "NotoSansUI-Regular.ttf" file from [Google's Noto fonts collection](https://www.google.com/get/noto/) , licensed under SIL OFL 1.1. 53 | 54 | -------------------------------------------------------------------------------- /assimp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(assimp_example) 3 | 4 | # required for GLU includes 5 | find_package(OpenGL REQUIRED) 6 | find_package(GLUT REQUIRED) 7 | 8 | # Use DownloadProject: https://github.com/Crascit/DownloadProject 9 | # cmake's ExternalProject < 3.8.0 has bugs when using URL download, 10 | # so don't attempt caching if using an older version 11 | if (CMAKE_VERSION VERSION_LESS 3.8) 12 | set(UPDATE_DISCONNECTED_IF_AVAILABLE "") 13 | else() 14 | set(UPDATE_DISCONNECTED_IF_AVAILABLE "UPDATE_DISCONNECTED 1") 15 | endif() 16 | 17 | # Add our project-specific Modules directory to the cmake module search path 18 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") 19 | 20 | include(DownloadProject) 21 | download_project(PROJ assimp 22 | URL https://github.com/assimp/assimp/archive/v4.1.0.tar.gz 23 | URL_HASH SHA1=ce3589f9455c743e993fd802bdaaed72838cd3f4 24 | ${UPDATE_DISCONNECTED_IF_AVAILABLE} 25 | ) 26 | 27 | # When including the library, no need for external tools 28 | set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE BOOL "" FORCE) 29 | 30 | # When including the library, no need for tests 31 | set(ASSIMP_BUILD_TESTS OFF CACHE BOOL "" FORCE) 32 | 33 | # This importer uses raw malloc()/free() calls, 34 | set(ASSIMP_BUILD_Q3BSP_IMPORTER OFF CACHE BOOL "" FORCE) 35 | 36 | # Force Assimp to build its internal copy of zlib 37 | set(ASSIMP_BUILD_ZLIB ON CACHE BOOL "" FORCE) 38 | 39 | add_subdirectory(${assimp_SOURCE_DIR} ${assimp_BINARY_DIR}) 40 | 41 | include_directories(include 42 | # Theoretically cmake should automatically pick up this directory, but it's easier to explicitly list it here. 43 | "${assimp_SOURCE_DIR}/include" 44 | # Assimp builds a custom config.h as part of its build, so also include the binary directory 45 | "${assimp_BINARY_DIR}/include" 46 | ${OPENGL_INCLUDE_DIR} 47 | ${GLUT_INCLUDE_DIR} 48 | ) 49 | 50 | add_executable(assimp_simpleogl 51 | src/Sample_SimpleOpenGL.c 52 | ) 53 | 54 | target_link_libraries(assimp_simpleogl 55 | ${OPENGL_LIBRARIES} 56 | ${GLUT_LIBRARIES} 57 | assimp 58 | ) 59 | 60 | # ./assimp_simpleogl assimp-src/test/models-nonbsd/X/dwarf.x 61 | -------------------------------------------------------------------------------- /assimp/README.md: -------------------------------------------------------------------------------- 1 | # Open Asset Import Library(assimp) 2 | [Assimp](http://assimp.org/) is a portable library to import 3D model formats in a uniform manner. It is an example of a well-meaning complicated import: the project maintains their own CMake system, but it is not usually installed directly to a packaging system. 3 | 4 | Since the library is special-purpose enough to assume it will not be present, we use the excellent [DownloadProject](https://github.com/Crascit/DownloadProject) CMake module to acquire the source at build-time, then incorporate it into our CMake build using `add_subdirectory()` 5 | 6 | ## Requirements: 7 | ### Linux: 8 | - freeglut3-dev 9 | - libxmu-dev 10 | 11 | ## Known bugs 12 | On OSX, if minizip is already installed on the system, linking to minizip during build finish may fail. 13 | This is due to assimp using outdated pkg-config macros from OGRE, which will automatically pick up the wrong link directory due to a [pkg-config quirk in CMake](https://cmake.org/Bug/view.php?id=15804) 14 | 15 | ## Project Layout 16 | 17 | ``` 18 | assimp 19 | |-- CMakeLists.txt 20 | |-- README.md 21 | |-- cmake 22 | | `-- Modules 23 | | |-- DownloadProject.CMakeLists.cmake.in 24 | | `-- DownloadProject.cmake 25 | `-- src 26 | `-- Sample_SimpleOpenGL.c 27 | ``` 28 | 29 | ## CMakeLists walkthrough 30 | ### CMakeLists.txt 31 | 32 | Declare our minimum CMake. DownloadProject is advanced enough that CMake 3.0 should be required. 33 | ``` 34 | cmake_minimum_required(VERSION 3.0) 35 | ``` 36 | Declare our project. This should always be the first statement outside of `cmake_minimum_required`, as most variables will not exist until this call. 37 | ``` 38 | project(assimp_example) 39 | ``` 40 | 41 | We require OpenGL and GLUT, so issue `find_package` calls to pick them up. 42 | ``` 43 | find_package(OpenGL REQUIRED) 44 | find_package(GLUT REQUIRED) 45 | ``` 46 | 47 | Before we load the DownloadProject module, we need to check CMake version: CMake < 3.8.0 has bugs in ExternalProject when using URL download, so don't attempt caching if using an older version 48 | ``` 49 | if (CMAKE_VERSION VERSION_LESS 3.8) 50 | set(UPDATE_DISCONNECTED_IF_AVAILABLE "") 51 | else() 52 | set(UPDATE_DISCONNECTED_IF_AVAILABLE "UPDATE_DISCONNECTED 1") 53 | endif() 54 | ``` 55 | 56 | Add our project-specific Modules directory to the cmake module search path 57 | ``` 58 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") 59 | ``` 60 | 61 | Finally, include the DownloadProject module and set our assimp download location. 62 | ``` 63 | include(DownloadProject) 64 | download_project(PROJ assimp 65 | URL https://github.com/assimp/assimp/archive/v4.1.0.tar.gz 66 | URL_HASH SHA1=ce3589f9455c743e993fd802bdaaed72838cd3f4 67 | ${UPDATE_DISCONNECTED_IF_AVAILABLE} 68 | ) 69 | ``` 70 | 71 | Assimp provides a CMake system, so we can set variables prior to `add_subdirectory`. 72 | 73 | Notably: we do not require the extra tools or tests, so we can disable them. The Q3BSP importer has raw malloc()/free() calls, so we prefer not to build that importer. Finally, we restrict assimp to using its embedded copy of zlib to avoid library linkage issues. 74 | 75 | Note that we use `CACHE BOOL "" FORCE` in our `set` commands. This is to get around a quirk of using assimp in a subdirectory provided by DownloadProject: normally we could simply `set` these and they would be picked up. But we need to force these in the top-level cache to ensure the separate download/src projects pick them up. This is a rare usage of using the Cache directly, and it is not encouraged for regular use. 76 | ``` 77 | set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE BOOL "" FORCE) 78 | set(ASSIMP_BUILD_TESTS OFF CACHE BOOL "" FORCE) 79 | set(ASSIMP_BUILD_Q3BSP_IMPORTER OFF CACHE BOOL "" FORCE) 80 | set(ASSIMP_BUILD_ZLIB ON CACHE BOOL "" FORCE) 81 | ``` 82 | 83 | Since assimp will be placed as two separate projects, we need to add both subdirectories(in particular, build-specific config headers will only be generated in ONE of them) 84 | ``` 85 | add_subdirectory(${assimp_SOURCE_DIR} ${assimp_BINARY_DIR}) 86 | ``` 87 | 88 | Include our directories. Theoretically CMake should automatically pick up the Assimp directory, but it's easier to explicitly list it here to avoid autodetection issues. 89 | ``` 90 | include_directories(include 91 | "${assimp_SOURCE_DIR}/include" 92 | "${assimp_BINARY_DIR}/include" 93 | ${OPENGL_INCLUDE_DIR} 94 | ${GLUT_INCLUDE_DIR} 95 | ) 96 | ``` 97 | 98 | Add our executable target. 99 | ``` 100 | add_executable(assimp_simpleogl 101 | src/Sample_SimpleOpenGL.c 102 | ) 103 | ``` 104 | 105 | Link our libraries. We have a `assimp` library variable at this point thanks to the `add_subdirectory` calls. 106 | ``` 107 | target_link_libraries(assimp_simpleogl 108 | ${OPENGL_LIBRARIES} 109 | ${GLUT_LIBRARIES} 110 | assimp 111 | ) 112 | ``` 113 | 114 | ## Use 115 | Let's make our build dir and run CMake. Note that as part of this, the Assimp source file will be downloaded BEFORE we issue a `make` call. 116 | ``` 117 | $ mkdir build 118 | $ cd build 119 | $ cmake .. 120 | ``` 121 | Make our project: 122 | ``` 123 | $ make 124 | ``` 125 | Then we can run our executable, using a sample file from the distribution. 126 | ``` 127 | $ ./assimp_simpleogl assimp-src/test/models-nonbsd/X/dwarf.x 128 | ``` 129 | -------------------------------------------------------------------------------- /assimp/cmake/Modules/DownloadProject.CMakeLists.cmake.in: -------------------------------------------------------------------------------- 1 | # Distributed under the OSI-approved MIT License. See accompanying 2 | # file LICENSE or https://github.com/Crascit/DownloadProject for details. 3 | 4 | cmake_minimum_required(VERSION 2.8.2) 5 | 6 | project(${DL_ARGS_PROJ}-download NONE) 7 | 8 | include(ExternalProject) 9 | ExternalProject_Add(${DL_ARGS_PROJ}-download 10 | ${DL_ARGS_UNPARSED_ARGUMENTS} 11 | SOURCE_DIR "${DL_ARGS_SOURCE_DIR}" 12 | BINARY_DIR "${DL_ARGS_BINARY_DIR}" 13 | CONFIGURE_COMMAND "" 14 | BUILD_COMMAND "" 15 | INSTALL_COMMAND "" 16 | TEST_COMMAND "" 17 | ) 18 | -------------------------------------------------------------------------------- /assimp/cmake/Modules/DownloadProject.cmake: -------------------------------------------------------------------------------- 1 | # Distributed under the OSI-approved MIT License. See accompanying 2 | # file LICENSE or https://github.com/Crascit/DownloadProject for details. 3 | # 4 | # MODULE: DownloadProject 5 | # 6 | # PROVIDES: 7 | # download_project( PROJ projectName 8 | # [PREFIX prefixDir] 9 | # [DOWNLOAD_DIR downloadDir] 10 | # [SOURCE_DIR srcDir] 11 | # [BINARY_DIR binDir] 12 | # [QUIET] 13 | # ... 14 | # ) 15 | # 16 | # Provides the ability to download and unpack a tarball, zip file, git repository, 17 | # etc. at configure time (i.e. when the cmake command is run). How the downloaded 18 | # and unpacked contents are used is up to the caller, but the motivating case is 19 | # to download source code which can then be included directly in the build with 20 | # add_subdirectory() after the call to download_project(). Source and build 21 | # directories are set up with this in mind. 22 | # 23 | # The PROJ argument is required. The projectName value will be used to construct 24 | # the following variables upon exit (obviously replace projectName with its actual 25 | # value): 26 | # 27 | # projectName_SOURCE_DIR 28 | # projectName_BINARY_DIR 29 | # 30 | # The SOURCE_DIR and BINARY_DIR arguments are optional and would not typically 31 | # need to be provided. They can be specified if you want the downloaded source 32 | # and build directories to be located in a specific place. The contents of 33 | # projectName_SOURCE_DIR and projectName_BINARY_DIR will be populated with the 34 | # locations used whether you provide SOURCE_DIR/BINARY_DIR or not. 35 | # 36 | # The DOWNLOAD_DIR argument does not normally need to be set. It controls the 37 | # location of the temporary CMake build used to perform the download. 38 | # 39 | # The PREFIX argument can be provided to change the base location of the default 40 | # values of DOWNLOAD_DIR, SOURCE_DIR and BINARY_DIR. If all of those three arguments 41 | # are provided, then PREFIX will have no effect. The default value for PREFIX is 42 | # CMAKE_BINARY_DIR. 43 | # 44 | # The QUIET option can be given if you do not want to show the output associated 45 | # with downloading the specified project. 46 | # 47 | # In addition to the above, any other options are passed through unmodified to 48 | # ExternalProject_Add() to perform the actual download, patch and update steps. 49 | # The following ExternalProject_Add() options are explicitly prohibited (they 50 | # are reserved for use by the download_project() command): 51 | # 52 | # CONFIGURE_COMMAND 53 | # BUILD_COMMAND 54 | # INSTALL_COMMAND 55 | # TEST_COMMAND 56 | # 57 | # Only those ExternalProject_Add() arguments which relate to downloading, patching 58 | # and updating of the project sources are intended to be used. Also note that at 59 | # least one set of download-related arguments are required. 60 | # 61 | # If using CMake 3.2 or later, the UPDATE_DISCONNECTED option can be used to 62 | # prevent a check at the remote end for changes every time CMake is run 63 | # after the first successful download. See the documentation of the ExternalProject 64 | # module for more information. It is likely you will want to use this option if it 65 | # is available to you. Note, however, that the ExternalProject implementation contains 66 | # bugs which result in incorrect handling of the UPDATE_DISCONNECTED option when 67 | # using the URL download method or when specifying a SOURCE_DIR with no download 68 | # method. Fixes for these have been created, the last of which is scheduled for 69 | # inclusion in CMake 3.8.0. Details can be found here: 70 | # 71 | # https://gitlab.kitware.com/cmake/cmake/commit/bdca68388bd57f8302d3c1d83d691034b7ffa70c 72 | # https://gitlab.kitware.com/cmake/cmake/issues/16428 73 | # 74 | # If you experience build errors related to the update step, consider avoiding 75 | # the use of UPDATE_DISCONNECTED. 76 | # 77 | # EXAMPLE USAGE: 78 | # 79 | # include(DownloadProject) 80 | # download_project(PROJ googletest 81 | # GIT_REPOSITORY https://github.com/google/googletest.git 82 | # GIT_TAG master 83 | # UPDATE_DISCONNECTED 1 84 | # QUIET 85 | # ) 86 | # 87 | # add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) 88 | # 89 | #======================================================================================== 90 | 91 | 92 | set(_DownloadProjectDir "${CMAKE_CURRENT_LIST_DIR}") 93 | 94 | include(CMakeParseArguments) 95 | 96 | function(download_project) 97 | 98 | set(options QUIET) 99 | set(oneValueArgs 100 | PROJ 101 | PREFIX 102 | DOWNLOAD_DIR 103 | SOURCE_DIR 104 | BINARY_DIR 105 | # Prevent the following from being passed through 106 | CONFIGURE_COMMAND 107 | BUILD_COMMAND 108 | INSTALL_COMMAND 109 | TEST_COMMAND 110 | ) 111 | set(multiValueArgs "") 112 | 113 | cmake_parse_arguments(DL_ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 114 | 115 | # Hide output if requested 116 | if (DL_ARGS_QUIET) 117 | set(OUTPUT_QUIET "OUTPUT_QUIET") 118 | else() 119 | unset(OUTPUT_QUIET) 120 | message(STATUS "Downloading/updating ${DL_ARGS_PROJ}") 121 | endif() 122 | 123 | # Set up where we will put our temporary CMakeLists.txt file and also 124 | # the base point below which the default source and binary dirs will be. 125 | # The prefix must always be an absolute path. 126 | if (NOT DL_ARGS_PREFIX) 127 | set(DL_ARGS_PREFIX "${CMAKE_BINARY_DIR}") 128 | else() 129 | get_filename_component(DL_ARGS_PREFIX "${DL_ARGS_PREFIX}" ABSOLUTE 130 | BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}") 131 | endif() 132 | if (NOT DL_ARGS_DOWNLOAD_DIR) 133 | set(DL_ARGS_DOWNLOAD_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-download") 134 | endif() 135 | 136 | # Ensure the caller can know where to find the source and build directories 137 | if (NOT DL_ARGS_SOURCE_DIR) 138 | set(DL_ARGS_SOURCE_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-src") 139 | endif() 140 | if (NOT DL_ARGS_BINARY_DIR) 141 | set(DL_ARGS_BINARY_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-build") 142 | endif() 143 | set(${DL_ARGS_PROJ}_SOURCE_DIR "${DL_ARGS_SOURCE_DIR}" PARENT_SCOPE) 144 | set(${DL_ARGS_PROJ}_BINARY_DIR "${DL_ARGS_BINARY_DIR}" PARENT_SCOPE) 145 | 146 | # The way that CLion manages multiple configurations, it causes a copy of 147 | # the CMakeCache.txt to be copied across due to it not expecting there to 148 | # be a project within a project. This causes the hard-coded paths in the 149 | # cache to be copied and builds to fail. To mitigate this, we simply 150 | # remove the cache if it exists before we configure the new project. It 151 | # is safe to do so because it will be re-generated. Since this is only 152 | # executed at the configure step, it should not cause additional builds or 153 | # downloads. 154 | file(REMOVE "${DL_ARGS_DOWNLOAD_DIR}/CMakeCache.txt") 155 | 156 | # Create and build a separate CMake project to carry out the download. 157 | # If we've already previously done these steps, they will not cause 158 | # anything to be updated, so extra rebuilds of the project won't occur. 159 | # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project 160 | # has this set to something not findable on the PATH. 161 | configure_file("${_DownloadProjectDir}/DownloadProject.CMakeLists.cmake.in" 162 | "${DL_ARGS_DOWNLOAD_DIR}/CMakeLists.txt") 163 | execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" 164 | -D "CMAKE_MAKE_PROGRAM:FILE=${CMAKE_MAKE_PROGRAM}" 165 | . 166 | RESULT_VARIABLE result 167 | ${OUTPUT_QUIET} 168 | WORKING_DIRECTORY "${DL_ARGS_DOWNLOAD_DIR}" 169 | ) 170 | if(result) 171 | message(FATAL_ERROR "CMake step for ${DL_ARGS_PROJ} failed: ${result}") 172 | endif() 173 | execute_process(COMMAND ${CMAKE_COMMAND} --build . 174 | RESULT_VARIABLE result 175 | ${OUTPUT_QUIET} 176 | WORKING_DIRECTORY "${DL_ARGS_DOWNLOAD_DIR}" 177 | ) 178 | if(result) 179 | message(FATAL_ERROR "Build step for ${DL_ARGS_PROJ} failed: ${result}") 180 | endif() 181 | 182 | endfunction() 183 | -------------------------------------------------------------------------------- /assimp/src/Sample_SimpleOpenGL.c: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | // Simple sample to prove that Assimp is easy to use with OpenGL. 3 | // It takes a file name as command line parameter, loads it using standard 4 | // settings and displays it. 5 | // 6 | // If you intend to _use_ this code sample in your app, do yourself a favour 7 | // and replace immediate mode calls with VBOs ... 8 | // 9 | // The vc8 solution links against assimp-release-dll_win32 - be sure to 10 | // have this configuration built. 11 | // ---------------------------------------------------------------------------- 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | #ifdef __APPLE__ 18 | #include 19 | #else 20 | #include 21 | #endif 22 | 23 | /* assimp include files. These three are usually needed. */ 24 | #include 25 | #include 26 | #include 27 | 28 | /* the global Assimp scene object */ 29 | const struct aiScene* scene = NULL; 30 | GLuint scene_list = 0; 31 | struct aiVector3D scene_min, scene_max, scene_center; 32 | 33 | /* current rotation angle */ 34 | static float angle = 0.f; 35 | 36 | #define aisgl_min(x,y) (xx?y:x) 38 | 39 | /* ---------------------------------------------------------------------------- */ 40 | void reshape(int width, int height) 41 | { 42 | const double aspectRatio = (float) width / height, fieldOfView = 45.0; 43 | 44 | glMatrixMode(GL_PROJECTION); 45 | glLoadIdentity(); 46 | gluPerspective(fieldOfView, aspectRatio, 47 | 1.0, 1000.0); /* Znear and Zfar */ 48 | glViewport(0, 0, width, height); 49 | } 50 | 51 | /* ---------------------------------------------------------------------------- */ 52 | void get_bounding_box_for_node (const struct aiNode* nd, 53 | struct aiVector3D* min, 54 | struct aiVector3D* max, 55 | struct aiMatrix4x4* trafo 56 | ){ 57 | struct aiMatrix4x4 prev; 58 | unsigned int n = 0, t; 59 | 60 | prev = *trafo; 61 | aiMultiplyMatrix4(trafo,&nd->mTransformation); 62 | 63 | for (; n < nd->mNumMeshes; ++n) { 64 | const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; 65 | for (t = 0; t < mesh->mNumVertices; ++t) { 66 | 67 | struct aiVector3D tmp = mesh->mVertices[t]; 68 | aiTransformVecByMatrix4(&tmp,trafo); 69 | 70 | min->x = aisgl_min(min->x,tmp.x); 71 | min->y = aisgl_min(min->y,tmp.y); 72 | min->z = aisgl_min(min->z,tmp.z); 73 | 74 | max->x = aisgl_max(max->x,tmp.x); 75 | max->y = aisgl_max(max->y,tmp.y); 76 | max->z = aisgl_max(max->z,tmp.z); 77 | } 78 | } 79 | 80 | for (n = 0; n < nd->mNumChildren; ++n) { 81 | get_bounding_box_for_node(nd->mChildren[n],min,max,trafo); 82 | } 83 | *trafo = prev; 84 | } 85 | 86 | /* ---------------------------------------------------------------------------- */ 87 | void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max) 88 | { 89 | struct aiMatrix4x4 trafo; 90 | aiIdentityMatrix4(&trafo); 91 | 92 | min->x = min->y = min->z = 1e10f; 93 | max->x = max->y = max->z = -1e10f; 94 | get_bounding_box_for_node(scene->mRootNode,min,max,&trafo); 95 | } 96 | 97 | /* ---------------------------------------------------------------------------- */ 98 | void color4_to_float4(const struct aiColor4D *c, float f[4]) 99 | { 100 | f[0] = c->r; 101 | f[1] = c->g; 102 | f[2] = c->b; 103 | f[3] = c->a; 104 | } 105 | 106 | /* ---------------------------------------------------------------------------- */ 107 | void set_float4(float f[4], float a, float b, float c, float d) 108 | { 109 | f[0] = a; 110 | f[1] = b; 111 | f[2] = c; 112 | f[3] = d; 113 | } 114 | 115 | /* ---------------------------------------------------------------------------- */ 116 | void apply_material(const struct aiMaterial *mtl) 117 | { 118 | float c[4]; 119 | 120 | GLenum fill_mode; 121 | int ret1, ret2; 122 | struct aiColor4D diffuse; 123 | struct aiColor4D specular; 124 | struct aiColor4D ambient; 125 | struct aiColor4D emission; 126 | ai_real shininess, strength; 127 | int two_sided; 128 | int wireframe; 129 | unsigned int max; 130 | 131 | set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f); 132 | if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse)) 133 | color4_to_float4(&diffuse, c); 134 | glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c); 135 | 136 | set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); 137 | if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular)) 138 | color4_to_float4(&specular, c); 139 | glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); 140 | 141 | set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f); 142 | if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient)) 143 | color4_to_float4(&ambient, c); 144 | glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c); 145 | 146 | set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); 147 | if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission)) 148 | color4_to_float4(&emission, c); 149 | glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c); 150 | 151 | max = 1; 152 | ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max); 153 | if(ret1 == AI_SUCCESS) { 154 | max = 1; 155 | ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max); 156 | if(ret2 == AI_SUCCESS) 157 | glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength); 158 | else 159 | glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); 160 | } 161 | else { 162 | glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); 163 | set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f); 164 | glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); 165 | } 166 | 167 | max = 1; 168 | if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max)) 169 | fill_mode = wireframe ? GL_LINE : GL_FILL; 170 | else 171 | fill_mode = GL_FILL; 172 | glPolygonMode(GL_FRONT_AND_BACK, fill_mode); 173 | 174 | max = 1; 175 | if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided) 176 | glDisable(GL_CULL_FACE); 177 | else 178 | glEnable(GL_CULL_FACE); 179 | } 180 | 181 | /* ---------------------------------------------------------------------------- */ 182 | void recursive_render (const struct aiScene *sc, const struct aiNode* nd) 183 | { 184 | unsigned int i; 185 | unsigned int n = 0, t; 186 | struct aiMatrix4x4 m = nd->mTransformation; 187 | 188 | /* update transform */ 189 | aiTransposeMatrix4(&m); 190 | glPushMatrix(); 191 | glMultMatrixf((float*)&m); 192 | 193 | /* draw all meshes assigned to this node */ 194 | for (; n < nd->mNumMeshes; ++n) { 195 | const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; 196 | 197 | apply_material(sc->mMaterials[mesh->mMaterialIndex]); 198 | 199 | if(mesh->mNormals == NULL) { 200 | glDisable(GL_LIGHTING); 201 | } else { 202 | glEnable(GL_LIGHTING); 203 | } 204 | 205 | for (t = 0; t < mesh->mNumFaces; ++t) { 206 | const struct aiFace* face = &mesh->mFaces[t]; 207 | GLenum face_mode; 208 | 209 | switch(face->mNumIndices) { 210 | case 1: face_mode = GL_POINTS; break; 211 | case 2: face_mode = GL_LINES; break; 212 | case 3: face_mode = GL_TRIANGLES; break; 213 | default: face_mode = GL_POLYGON; break; 214 | } 215 | 216 | glBegin(face_mode); 217 | 218 | for(i = 0; i < face->mNumIndices; i++) { 219 | int index = face->mIndices[i]; 220 | if(mesh->mColors[0] != NULL) 221 | glColor4fv((GLfloat*)&mesh->mColors[0][index]); 222 | if(mesh->mNormals != NULL) 223 | glNormal3fv(&mesh->mNormals[index].x); 224 | glVertex3fv(&mesh->mVertices[index].x); 225 | } 226 | 227 | glEnd(); 228 | } 229 | 230 | } 231 | 232 | /* draw all children */ 233 | for (n = 0; n < nd->mNumChildren; ++n) { 234 | recursive_render(sc, nd->mChildren[n]); 235 | } 236 | 237 | glPopMatrix(); 238 | } 239 | 240 | /* ---------------------------------------------------------------------------- */ 241 | void do_motion (void) 242 | { 243 | static GLint prev_time = 0; 244 | static GLint prev_fps_time = 0; 245 | static int frames = 0; 246 | 247 | int time = glutGet(GLUT_ELAPSED_TIME); 248 | angle += (time-prev_time)*0.01; 249 | prev_time = time; 250 | 251 | frames += 1; 252 | if ((time - prev_fps_time) > 1000) /* update every seconds */ 253 | { 254 | int current_fps = frames * 1000 / (time - prev_fps_time); 255 | printf("%d fps\n", current_fps); 256 | frames = 0; 257 | prev_fps_time = time; 258 | } 259 | 260 | 261 | glutPostRedisplay (); 262 | } 263 | 264 | /* ---------------------------------------------------------------------------- */ 265 | void display(void) 266 | { 267 | float tmp; 268 | 269 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 270 | 271 | glMatrixMode(GL_MODELVIEW); 272 | glLoadIdentity(); 273 | gluLookAt(0.f,0.f,3.f,0.f,0.f,-5.f,0.f,1.f,0.f); 274 | 275 | /* rotate it around the y axis */ 276 | glRotatef(angle,0.f,1.f,0.f); 277 | 278 | /* scale the whole asset to fit into our view frustum */ 279 | tmp = scene_max.x-scene_min.x; 280 | tmp = aisgl_max(scene_max.y - scene_min.y,tmp); 281 | tmp = aisgl_max(scene_max.z - scene_min.z,tmp); 282 | tmp = 1.f / tmp; 283 | glScalef(tmp, tmp, tmp); 284 | 285 | /* center the model */ 286 | glTranslatef( -scene_center.x, -scene_center.y, -scene_center.z ); 287 | 288 | /* if the display list has not been made yet, create a new one and 289 | fill it with scene contents */ 290 | if(scene_list == 0) { 291 | scene_list = glGenLists(1); 292 | glNewList(scene_list, GL_COMPILE); 293 | /* now begin at the root node of the imported data and traverse 294 | the scenegraph by multiplying subsequent local transforms 295 | together on GL's matrix stack. */ 296 | recursive_render(scene, scene->mRootNode); 297 | glEndList(); 298 | } 299 | 300 | glCallList(scene_list); 301 | 302 | glutSwapBuffers(); 303 | 304 | do_motion(); 305 | } 306 | 307 | /* ---------------------------------------------------------------------------- */ 308 | int loadasset (const char* path) 309 | { 310 | /* we are taking one of the postprocessing presets to avoid 311 | spelling out 20+ single postprocessing flags here. */ 312 | scene = aiImportFile(path,aiProcessPreset_TargetRealtime_MaxQuality); 313 | 314 | if (scene) { 315 | get_bounding_box(&scene_min,&scene_max); 316 | scene_center.x = (scene_min.x + scene_max.x) / 2.0f; 317 | scene_center.y = (scene_min.y + scene_max.y) / 2.0f; 318 | scene_center.z = (scene_min.z + scene_max.z) / 2.0f; 319 | return 0; 320 | } 321 | return 1; 322 | } 323 | 324 | /* ---------------------------------------------------------------------------- */ 325 | int main(int argc, char **argv) 326 | { 327 | struct aiLogStream stream; 328 | 329 | glutInitWindowSize(900,600); 330 | glutInitWindowPosition(100,100); 331 | glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 332 | glutInit(&argc, argv); 333 | 334 | glutCreateWindow("Assimp - Very simple OpenGL sample"); 335 | glutDisplayFunc(display); 336 | glutReshapeFunc(reshape); 337 | 338 | /* get a handle to the predefined STDOUT log stream and attach 339 | it to the logging system. It remains active for all further 340 | calls to aiImportFile(Ex) and aiApplyPostProcessing. */ 341 | stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL); 342 | aiAttachLogStream(&stream); 343 | 344 | /* ... same procedure, but this stream now writes the 345 | log messages to assimp_log.txt */ 346 | stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt"); 347 | aiAttachLogStream(&stream); 348 | 349 | /* the model name can be specified on the command line. If none 350 | is specified, we try to locate one of the more expressive test 351 | models from the repository (/models-nonbsd may be missing in 352 | some distributions so we need a fallback from /models!). */ 353 | if( 0 != loadasset( argc >= 2 ? argv[1] : "../../test/models-nonbsd/X/dwarf.x")) { 354 | if( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) { 355 | return -1; 356 | } 357 | } 358 | 359 | glClearColor(0.1f,0.1f,0.1f,1.f); 360 | 361 | glEnable(GL_LIGHTING); 362 | glEnable(GL_LIGHT0); /* Uses default lighting parameters */ 363 | 364 | glEnable(GL_DEPTH_TEST); 365 | 366 | glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); 367 | glEnable(GL_NORMALIZE); 368 | 369 | /* XXX docs say all polygons are emitted CCW, but tests show that some aren't. */ 370 | if(getenv("MODEL_IS_BROKEN")) 371 | glFrontFace(GL_CW); 372 | 373 | glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); 374 | 375 | glutGet(GLUT_ELAPSED_TIME); 376 | glutMainLoop(); 377 | 378 | /* cleanup - calling 'aiReleaseImport' is important, as the library 379 | keeps internal resources until the scene is freed again. Not 380 | doing so can cause severe resource leaking. */ 381 | aiReleaseImport(scene); 382 | 383 | /* We added a log stream to the library, it's our job to disable it 384 | again. This will definitely release the last resources allocated 385 | by Assimp.*/ 386 | aiDetachAllLogStreams(); 387 | return 0; 388 | } 389 | -------------------------------------------------------------------------------- /imgui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(imgui_example) 3 | 4 | # For the straight OpenGL2 example 5 | find_package(glfw3 CONFIG REQUIRED) 6 | # required for GLU includes 7 | find_package(OpenGL) 8 | 9 | # No need for a specialised FindSDL2.cmake module, as of 3.9.3+(?) 10 | find_package(SDL2) 11 | 12 | add_subdirectory(libs/imgui) 13 | 14 | if(APPLE) 15 | # OSX does not include X11 by default and some SDL2 installations require it, so add it here. 16 | find_package(X11) 17 | include_directories(include 18 | libs/imgui/include 19 | ${OPENGL_INCLUDE_DIR} 20 | ${glfw3_INCLUDE_DIRS} 21 | ${SDL2_INCLUDE_DIRS} 22 | ${X11_INCLUDE_DIR} 23 | ) 24 | else() 25 | include_directories(include 26 | libs/imgui/include 27 | ${OPENGL_INCLUDE_DIR} 28 | ${glfw3_INCLUDE_DIRS} 29 | ${SDL2_INCLUDE_DIRS} 30 | ) 31 | endif(APPLE) 32 | # The sample using OpenGL2 and GLFW window 33 | add_executable(opengl2_example 34 | src/main.cpp 35 | src/imgui_impl_glfw.cpp 36 | ) 37 | 38 | target_link_libraries(opengl2_example 39 | imgui 40 | ${OPENGL_LIBRARIES} 41 | glfw 42 | ) 43 | 44 | # The sample using OpenGL2 and SDL window 45 | add_executable(sdl_opengl2_example 46 | src/main_sdl.cpp 47 | src/imgui_impl_sdl.cpp 48 | ) 49 | 50 | target_link_libraries(sdl_opengl2_example 51 | imgui 52 | ${SDL2_LIBRARIES} 53 | ${OPENGL_LIBRARIES} 54 | ) 55 | -------------------------------------------------------------------------------- /imgui/README.md: -------------------------------------------------------------------------------- 1 | # ImGui 2 | [ImGui](https://github.com/ocornut/imgui) is a slim GUI library for C++. It is framework-agnostic, merely outputting a list of draw commands. This project shows the use of OpenGL, with window support from both GLFW and SDL2. 3 | 4 | Since ImGui does not enforce any project layout, its files have been reorganized into a separate library directory. No changes have been made, and this should not be considered gospel: it's just one of many ways a developer could include them. 5 | 6 | ## Requirements 7 | 8 | Linux: 9 | - libsdl2-dev 10 | 11 | BSD: 12 | - sdl2 13 | 14 | OSX: 15 | - LibSDL2 16 | 17 | ## Project Layout 18 | 19 | ``` 20 | imgui 21 | |-- CMakeLists.txt 22 | |-- README.md 23 | |-- include 24 | | |-- imgui_impl_glfw.h 25 | | `-- imgui_impl_sdl.h 26 | |-- libs 27 | | `-- imgui 28 | | |-- CMakeLists.txt 29 | | |-- LICENSE.txt 30 | | |-- imgui.cpp 31 | | |-- imgui_demo.cpp 32 | | |-- imgui_draw.cpp 33 | | `-- include 34 | | |-- imconfig.h 35 | | |-- imgui.h 36 | | |-- imgui_internal.h 37 | | |-- stb_rect_pack.h 38 | | |-- stb_textedit.h 39 | | `-- stb_truetype.h 40 | `-- src 41 | |-- imgui_impl_glfw.cpp 42 | |-- imgui_impl_sdl.cpp 43 | |-- main.cpp 44 | `-- main_sdl.cpp 45 | ``` 46 | 47 | ## CMakeLists walkthrough 48 | ### CMakeLists.txt 49 | Declare our minimum cmake. There are no real advanced features used, so I usually use 2.8 as an absolute minimum. In 2018+ it's probably safe to use at least 3.0. 50 | ``` 51 | cmake_minimum_required(VERSION 2.8) 52 | ``` 53 | Declare our project. This should always be the first statement outside of `cmake_minimum_required`, as most variables will not exist until this call. 54 | ``` 55 | project(imgui_example) 56 | ``` 57 | 58 | glfw is usually shipped as 'glfw3', so take that into account. Note the use of `CONFIG` in the `find_package` call: this is because CMake ships a `glfw3Config.cmake` file OUTSIDE of our project. 59 | This [StackOverflow answer](https://stackoverflow.com/questions/20746936/cmake-of-what-use-is-find-package-if-you-need-to-specify-cmake-module-path-an) is a good in-depth look at the difference between Module and Config modes in `find_package` 60 | ``` 61 | find_package(glfw3 CONFIG REQUIRED) 62 | ``` 63 | OpenGL(specifically GLU) is required, so request it here 64 | ``` 65 | find_package(OpenGL) 66 | ``` 67 | 68 | CMake has shipped a FindSDL2.cmake module for quite awhile, so a simple `find_package` is all that's required. 69 | ``` 70 | find_package(SDL2) 71 | ``` 72 | 73 | We have imported all of the packages we need, so it is safe to include the ImGui subdirectory in `libs`. 74 | One of the easily-overlooked quirks of CMake is that every CMakeLists.txt file creates its own variable space. Much like `fork()` in Unix, the child CMakeLists.txt file will INHERIT variables from the parent, but after that is expected to keep its own. If you expect to use libraries or variables in subdirectories, they must be set BEFORE the `add_subdirectory` call. 75 | (There are ways around this as demonstrated in the _assimp_ project, but they are not meant to be used on a regular basis) 76 | ``` 77 | add_subdirectory(libs/imgui) 78 | ``` 79 | 80 | Depending on how SDL2 is installed, it may require X11 libraries. Most systems will handle this OK, but OSX has dropped X11 out of its main developer trees. Most OSX packaging systems will then include it, but this isn't detected-by-default with CMake. 81 | 82 | We use a simple conditional to check for an OSX system, then add the extra `find_package` and `include_directories` list. 83 | ``` 84 | if(APPLE) 85 | find_package(X11) 86 | include_directories(include 87 | libs/imgui/include 88 | ${OPENGL_INCLUDE_DIR} 89 | ${glfw3_INCLUDE_DIRS} 90 | ${SDL2_INCLUDE_DIRS} 91 | ${X11_INCLUDE_DIR} 92 | ) 93 | ``` 94 | If we are not in OSX, there's nothing to do. 95 | ``` 96 | else() 97 | include_directories(include 98 | libs/imgui/include 99 | ${OPENGL_INCLUDE_DIR} 100 | ${glfw3_INCLUDE_DIRS} 101 | ${SDL2_INCLUDE_DIRS} 102 | ) 103 | ``` 104 | Explicitly close our `if` tree. The `if` command is one of the oldest in CMake, so it still retains a few quirks. Happily, the `APPLE` flag is internal to CMake, so there is no string-escaping required. 105 | ``` 106 | endif(APPLE) 107 | ``` 108 | 109 | Declare our OpenGL2 example using GLFW 110 | ``` 111 | add_executable(opengl2_example 112 | src/main.cpp 113 | src/imgui_impl_glfw.cpp 114 | ) 115 | ``` 116 | 117 | Link the ImGui, opengl, and glfw libraries. We have a `imgui` library variable at this point thanks to the `add_subdirectory` call earlier. 118 | ``` 119 | target_link_libraries(opengl2_example 120 | imgui 121 | ${OPENGL_LIBRARIES} 122 | glfw 123 | ) 124 | ``` 125 | 126 | Declare our OpenGL2 example using SDL2 127 | ``` 128 | add_executable(sdl_opengl2_example 129 | src/main_sdl.cpp 130 | src/imgui_impl_sdl.cpp 131 | ) 132 | ``` 133 | 134 | Link against our requested libraries. 135 | ``` 136 | target_link_libraries(sdl_opengl2_example 137 | imgui 138 | ${SDL2_LIBRARIES} 139 | ${OPENGL_LIBRARIES} 140 | ) 141 | ``` 142 | ### libs/imgui/CMakeLists.txt 143 | Since we are in a subdirectory, we already have a cmake version requirement and a project declared. All that's left is to just declare the library that ImGui builds. 144 | 145 | I like to put `STATUS` messages in subdirectory files, if only because it can help debugging later. There is no requirement to do so. 146 | ``` 147 | message(STATUS "processing imgui") 148 | ``` 149 | 150 | ImGui provides a separate include directory. 151 | ``` 152 | include_directories(include) 153 | ``` 154 | ImGui is a few source files. By default `add_library` will build a static library, which is fine for a single executable. 155 | ``` 156 | add_library(imgui 157 | imgui.cpp 158 | imgui_demo.cpp 159 | imgui_draw.cpp 160 | ) 161 | ``` 162 | ## Use 163 | Let's make our build dir and run cmake: 164 | ``` 165 | $ mkdir build 166 | $ cd build 167 | $ cmake .. 168 | ``` 169 | 170 | Then we can make our project. Note that ImGui will be built as a static library before our executable: 171 | ``` 172 | $ make 173 | Scanning dependencies of target imgui 174 | [ 10%] Building CXX object libs/imgui/CMakeFiles/imgui.dir/imgui.cpp.o 175 | [ 20%] Building CXX object libs/imgui/CMakeFiles/imgui.dir/imgui_demo.cpp.o 176 | [ 30%] Building CXX object libs/imgui/CMakeFiles/imgui.dir/imgui_draw.cpp.o 177 | [ 40%] Linking CXX static library libimgui.a 178 | [ 40%] Built target imgui 179 | Scanning dependencies of target sdl_opengl2_example 180 | [ 50%] Building CXX object CMakeFiles/sdl_opengl2_example.dir/src/main_sdl.cpp.o 181 | [ 60%] Building CXX object CMakeFiles/sdl_opengl2_example.dir/src/imgui_impl_sdl.cpp.o 182 | [ 70%] Linking CXX executable sdl_opengl2_example 183 | [ 70%] Built target sdl_opengl2_example 184 | Scanning dependencies of target opengl2_example 185 | [ 80%] Building CXX object CMakeFiles/opengl2_example.dir/src/main.cpp.o 186 | [ 90%] Building CXX object CMakeFiles/opengl2_example.dir/src/imgui_impl_glfw.cpp.o 187 | [100%] Linking CXX executable opengl2_example 188 | [100%] Built target opengl2_example 189 | ``` 190 | And then we can run our executables: 191 | ``` 192 | $ ./opengl2_example 193 | $ ./sdl_opengl2_example 194 | ``` 195 | -------------------------------------------------------------------------------- /imgui/include/imgui_impl_glfw.h: -------------------------------------------------------------------------------- 1 | // ImGui GLFW binding with OpenGL (legacy, fixed pipeline) 2 | // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. 3 | // (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) 4 | 5 | // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** 6 | // **Prefer using the code in the opengl3_example/ folder** 7 | // See imgui_impl_glfw.cpp for details. 8 | 9 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 10 | // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). 11 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 12 | // https://github.com/ocornut/imgui 13 | 14 | struct GLFWwindow; 15 | 16 | IMGUI_API bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks); 17 | IMGUI_API void ImGui_ImplGlfwGL2_Shutdown(); 18 | IMGUI_API void ImGui_ImplGlfwGL2_NewFrame(); 19 | 20 | // Use if you want to reset your rendering device without losing ImGui state. 21 | IMGUI_API void ImGui_ImplGlfwGL2_InvalidateDeviceObjects(); 22 | IMGUI_API bool ImGui_ImplGlfwGL2_CreateDeviceObjects(); 23 | 24 | // GLFW callbacks (registered by default to GLFW if you enable 'install_callbacks' during initialization) 25 | // Provided here if you want to chain callbacks yourself. You may also handle inputs yourself and use those as a reference. 26 | IMGUI_API void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); 27 | IMGUI_API void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); 28 | IMGUI_API void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); 29 | IMGUI_API void ImGui_ImplGlfwGL2_CharCallback(GLFWwindow* window, unsigned int c); 30 | -------------------------------------------------------------------------------- /imgui/include/imgui_impl_sdl.h: -------------------------------------------------------------------------------- 1 | // ImGui SDL2 binding with OpenGL (legacy, fixed pipeline) 2 | // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. 3 | // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) 4 | 5 | // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** 6 | // **Prefer using the code in the sdl_opengl3_example/ folder** 7 | // See imgui_impl_sdl.cpp for details. 8 | 9 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 10 | // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). 11 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 12 | // https://github.com/ocornut/imgui 13 | 14 | struct SDL_Window; 15 | typedef union SDL_Event SDL_Event; 16 | 17 | IMGUI_API bool ImGui_ImplSdlGL2_Init(SDL_Window* window); 18 | IMGUI_API void ImGui_ImplSdlGL2_Shutdown(); 19 | IMGUI_API void ImGui_ImplSdlGL2_NewFrame(SDL_Window* window); 20 | IMGUI_API bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event); 21 | 22 | // Use if you want to reset your rendering device without losing ImGui state. 23 | IMGUI_API void ImGui_ImplSdlGL2_InvalidateDeviceObjects(); 24 | IMGUI_API bool ImGui_ImplSdlGL2_CreateDeviceObjects(); 25 | -------------------------------------------------------------------------------- /imgui/libs/imgui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | message(STATUS "processing imgui") 2 | 3 | include_directories(include) 4 | add_library(imgui 5 | imgui.cpp 6 | imgui_demo.cpp 7 | imgui_draw.cpp 8 | ) 9 | -------------------------------------------------------------------------------- /imgui/libs/imgui/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2017 Omar Cornut and ImGui contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /imgui/libs/imgui/include/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // USER IMPLEMENTATION 3 | // This file contains compile-time options for ImGui. 4 | // Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO(). 5 | //----------------------------------------------------------------------------- 6 | 7 | #pragma once 8 | 9 | //---- Define assertion handler. Defaults to calling assert(). 10 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 11 | 12 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows. 13 | //#define IMGUI_API __declspec( dllexport ) 14 | //#define IMGUI_API __declspec( dllimport ) 15 | 16 | //---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names 17 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 18 | 19 | //---- Include imgui_user.h at the end of imgui.h 20 | //#define IMGUI_INCLUDE_IMGUI_USER_H 21 | 22 | //---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions) 23 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS 24 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS 25 | 26 | //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) 27 | //---- It is very strongly recommended to NOT disable the demo windows. Please read the comment at the top of imgui_demo.cpp to learn why. 28 | //#define IMGUI_DISABLE_DEMO_WINDOWS 29 | 30 | //---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself. 31 | //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS 32 | 33 | //---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends) 34 | //#define IMGUI_USE_BGRA_PACKED_COLOR 35 | 36 | //---- Implement STB libraries in a namespace to avoid linkage conflicts 37 | //#define IMGUI_STB_NAMESPACE ImGuiStb 38 | 39 | //---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. 40 | /* 41 | #define IM_VEC2_CLASS_EXTRA \ 42 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 43 | operator MyVec2() const { return MyVec2(x,y); } 44 | 45 | #define IM_VEC4_CLASS_EXTRA \ 46 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 47 | operator MyVec4() const { return MyVec4(x,y,z,w); } 48 | */ 49 | 50 | //---- Use 32-bit vertex indices (instead of default: 16-bit) to allow meshes with more than 64K vertices 51 | //#define ImDrawIdx unsigned int 52 | 53 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 54 | //---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers. 55 | /* 56 | namespace ImGui 57 | { 58 | void Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL); 59 | } 60 | */ 61 | 62 | -------------------------------------------------------------------------------- /imgui/libs/imgui/include/stb_rect_pack.h: -------------------------------------------------------------------------------- 1 | // stb_rect_pack.h - v0.10 - public domain - rectangle packing 2 | // Sean Barrett 2014 3 | // 4 | // Useful for e.g. packing rectangular textures into an atlas. 5 | // Does not do rotation. 6 | // 7 | // Not necessarily the awesomest packing method, but better than 8 | // the totally naive one in stb_truetype (which is primarily what 9 | // this is meant to replace). 10 | // 11 | // Has only had a few tests run, may have issues. 12 | // 13 | // More docs to come. 14 | // 15 | // No memory allocations; uses qsort() and assert() from stdlib. 16 | // Can override those by defining STBRP_SORT and STBRP_ASSERT. 17 | // 18 | // This library currently uses the Skyline Bottom-Left algorithm. 19 | // 20 | // Please note: better rectangle packers are welcome! Please 21 | // implement them to the same API, but with a different init 22 | // function. 23 | // 24 | // Credits 25 | // 26 | // Library 27 | // Sean Barrett 28 | // Minor features 29 | // Martins Mozeiko 30 | // Bugfixes / warning fixes 31 | // Jeremy Jaussaud 32 | // 33 | // Version history: 34 | // 35 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings 36 | // 0.09 (2016-08-27) fix compiler warnings 37 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) 38 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) 39 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort 40 | // 0.05: added STBRP_ASSERT to allow replacing assert 41 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support 42 | // 0.01: initial release 43 | // 44 | // LICENSE 45 | // 46 | // This software is dual-licensed to the public domain and under the following 47 | // license: you are granted a perpetual, irrevocable license to copy, modify, 48 | // publish, and distribute this file as you see fit. 49 | 50 | ////////////////////////////////////////////////////////////////////////////// 51 | // 52 | // INCLUDE SECTION 53 | // 54 | 55 | #ifndef STB_INCLUDE_STB_RECT_PACK_H 56 | #define STB_INCLUDE_STB_RECT_PACK_H 57 | 58 | #define STB_RECT_PACK_VERSION 1 59 | 60 | #ifdef STBRP_STATIC 61 | #define STBRP_DEF static 62 | #else 63 | #define STBRP_DEF extern 64 | #endif 65 | 66 | #ifdef __cplusplus 67 | extern "C" { 68 | #endif 69 | 70 | typedef struct stbrp_context stbrp_context; 71 | typedef struct stbrp_node stbrp_node; 72 | typedef struct stbrp_rect stbrp_rect; 73 | 74 | #ifdef STBRP_LARGE_RECTS 75 | typedef int stbrp_coord; 76 | #else 77 | typedef unsigned short stbrp_coord; 78 | #endif 79 | 80 | STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); 81 | // Assign packed locations to rectangles. The rectangles are of type 82 | // 'stbrp_rect' defined below, stored in the array 'rects', and there 83 | // are 'num_rects' many of them. 84 | // 85 | // Rectangles which are successfully packed have the 'was_packed' flag 86 | // set to a non-zero value and 'x' and 'y' store the minimum location 87 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left 88 | // if you imagine y increasing downwards). Rectangles which do not fit 89 | // have the 'was_packed' flag set to 0. 90 | // 91 | // You should not try to access the 'rects' array from another thread 92 | // while this function is running, as the function temporarily reorders 93 | // the array while it executes. 94 | // 95 | // To pack into another rectangle, you need to call stbrp_init_target 96 | // again. To continue packing into the same rectangle, you can call 97 | // this function again. Calling this multiple times with multiple rect 98 | // arrays will probably produce worse packing results than calling it 99 | // a single time with the full rectangle array, but the option is 100 | // available. 101 | 102 | struct stbrp_rect 103 | { 104 | // reserved for your use: 105 | int id; 106 | 107 | // input: 108 | stbrp_coord w, h; 109 | 110 | // output: 111 | stbrp_coord x, y; 112 | int was_packed; // non-zero if valid packing 113 | 114 | }; // 16 bytes, nominally 115 | 116 | 117 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); 118 | // Initialize a rectangle packer to: 119 | // pack a rectangle that is 'width' by 'height' in dimensions 120 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long 121 | // 122 | // You must call this function every time you start packing into a new target. 123 | // 124 | // There is no "shutdown" function. The 'nodes' memory must stay valid for 125 | // the following stbrp_pack_rects() call (or calls), but can be freed after 126 | // the call (or calls) finish. 127 | // 128 | // Note: to guarantee best results, either: 129 | // 1. make sure 'num_nodes' >= 'width' 130 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' 131 | // 132 | // If you don't do either of the above things, widths will be quantized to multiples 133 | // of small integers to guarantee the algorithm doesn't run out of temporary storage. 134 | // 135 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm 136 | // may run out of temporary storage and be unable to pack some rectangles. 137 | 138 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); 139 | // Optionally call this function after init but before doing any packing to 140 | // change the handling of the out-of-temp-memory scenario, described above. 141 | // If you call init again, this will be reset to the default (false). 142 | 143 | 144 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); 145 | // Optionally select which packing heuristic the library should use. Different 146 | // heuristics will produce better/worse results for different data sets. 147 | // If you call init again, this will be reset to the default. 148 | 149 | enum 150 | { 151 | STBRP_HEURISTIC_Skyline_default=0, 152 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, 153 | STBRP_HEURISTIC_Skyline_BF_sortHeight 154 | }; 155 | 156 | 157 | ////////////////////////////////////////////////////////////////////////////// 158 | // 159 | // the details of the following structures don't matter to you, but they must 160 | // be visible so you can handle the memory allocations for them 161 | 162 | struct stbrp_node 163 | { 164 | stbrp_coord x,y; 165 | stbrp_node *next; 166 | }; 167 | 168 | struct stbrp_context 169 | { 170 | int width; 171 | int height; 172 | int align; 173 | int init_mode; 174 | int heuristic; 175 | int num_nodes; 176 | stbrp_node *active_head; 177 | stbrp_node *free_head; 178 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' 179 | }; 180 | 181 | #ifdef __cplusplus 182 | } 183 | #endif 184 | 185 | #endif 186 | 187 | ////////////////////////////////////////////////////////////////////////////// 188 | // 189 | // IMPLEMENTATION SECTION 190 | // 191 | 192 | #ifdef STB_RECT_PACK_IMPLEMENTATION 193 | #ifndef STBRP_SORT 194 | #include 195 | #define STBRP_SORT qsort 196 | #endif 197 | 198 | #ifndef STBRP_ASSERT 199 | #include 200 | #define STBRP_ASSERT assert 201 | #endif 202 | 203 | #ifdef _MSC_VER 204 | #define STBRP__NOTUSED(v) (void)(v) 205 | #else 206 | #define STBRP__NOTUSED(v) (void)sizeof(v) 207 | #endif 208 | 209 | enum 210 | { 211 | STBRP__INIT_skyline = 1 212 | }; 213 | 214 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) 215 | { 216 | switch (context->init_mode) { 217 | case STBRP__INIT_skyline: 218 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); 219 | context->heuristic = heuristic; 220 | break; 221 | default: 222 | STBRP_ASSERT(0); 223 | } 224 | } 225 | 226 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) 227 | { 228 | if (allow_out_of_mem) 229 | // if it's ok to run out of memory, then don't bother aligning them; 230 | // this gives better packing, but may fail due to OOM (even though 231 | // the rectangles easily fit). @TODO a smarter approach would be to only 232 | // quantize once we've hit OOM, then we could get rid of this parameter. 233 | context->align = 1; 234 | else { 235 | // if it's not ok to run out of memory, then quantize the widths 236 | // so that num_nodes is always enough nodes. 237 | // 238 | // I.e. num_nodes * align >= width 239 | // align >= width / num_nodes 240 | // align = ceil(width/num_nodes) 241 | 242 | context->align = (context->width + context->num_nodes-1) / context->num_nodes; 243 | } 244 | } 245 | 246 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) 247 | { 248 | int i; 249 | #ifndef STBRP_LARGE_RECTS 250 | STBRP_ASSERT(width <= 0xffff && height <= 0xffff); 251 | #endif 252 | 253 | for (i=0; i < num_nodes-1; ++i) 254 | nodes[i].next = &nodes[i+1]; 255 | nodes[i].next = NULL; 256 | context->init_mode = STBRP__INIT_skyline; 257 | context->heuristic = STBRP_HEURISTIC_Skyline_default; 258 | context->free_head = &nodes[0]; 259 | context->active_head = &context->extra[0]; 260 | context->width = width; 261 | context->height = height; 262 | context->num_nodes = num_nodes; 263 | stbrp_setup_allow_out_of_mem(context, 0); 264 | 265 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) 266 | context->extra[0].x = 0; 267 | context->extra[0].y = 0; 268 | context->extra[0].next = &context->extra[1]; 269 | context->extra[1].x = (stbrp_coord) width; 270 | #ifdef STBRP_LARGE_RECTS 271 | context->extra[1].y = (1<<30); 272 | #else 273 | context->extra[1].y = 65535; 274 | #endif 275 | context->extra[1].next = NULL; 276 | } 277 | 278 | // find minimum y position if it starts at x1 279 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) 280 | { 281 | stbrp_node *node = first; 282 | int x1 = x0 + width; 283 | int min_y, visited_width, waste_area; 284 | 285 | STBRP__NOTUSED(c); 286 | 287 | STBRP_ASSERT(first->x <= x0); 288 | 289 | #if 0 290 | // skip in case we're past the node 291 | while (node->next->x <= x0) 292 | ++node; 293 | #else 294 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency 295 | #endif 296 | 297 | STBRP_ASSERT(node->x <= x0); 298 | 299 | min_y = 0; 300 | waste_area = 0; 301 | visited_width = 0; 302 | while (node->x < x1) { 303 | if (node->y > min_y) { 304 | // raise min_y higher. 305 | // we've accounted for all waste up to min_y, 306 | // but we'll now add more waste for everything we've visted 307 | waste_area += visited_width * (node->y - min_y); 308 | min_y = node->y; 309 | // the first time through, visited_width might be reduced 310 | if (node->x < x0) 311 | visited_width += node->next->x - x0; 312 | else 313 | visited_width += node->next->x - node->x; 314 | } else { 315 | // add waste area 316 | int under_width = node->next->x - node->x; 317 | if (under_width + visited_width > width) 318 | under_width = width - visited_width; 319 | waste_area += under_width * (min_y - node->y); 320 | visited_width += under_width; 321 | } 322 | node = node->next; 323 | } 324 | 325 | *pwaste = waste_area; 326 | return min_y; 327 | } 328 | 329 | typedef struct 330 | { 331 | int x,y; 332 | stbrp_node **prev_link; 333 | } stbrp__findresult; 334 | 335 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) 336 | { 337 | int best_waste = (1<<30), best_x, best_y = (1 << 30); 338 | stbrp__findresult fr; 339 | stbrp_node **prev, *node, *tail, **best = NULL; 340 | 341 | // align to multiple of c->align 342 | width = (width + c->align - 1); 343 | width -= width % c->align; 344 | STBRP_ASSERT(width % c->align == 0); 345 | 346 | node = c->active_head; 347 | prev = &c->active_head; 348 | while (node->x + width <= c->width) { 349 | int y,waste; 350 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); 351 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL 352 | // bottom left 353 | if (y < best_y) { 354 | best_y = y; 355 | best = prev; 356 | } 357 | } else { 358 | // best-fit 359 | if (y + height <= c->height) { 360 | // can only use it if it first vertically 361 | if (y < best_y || (y == best_y && waste < best_waste)) { 362 | best_y = y; 363 | best_waste = waste; 364 | best = prev; 365 | } 366 | } 367 | } 368 | prev = &node->next; 369 | node = node->next; 370 | } 371 | 372 | best_x = (best == NULL) ? 0 : (*best)->x; 373 | 374 | // if doing best-fit (BF), we also have to try aligning right edge to each node position 375 | // 376 | // e.g, if fitting 377 | // 378 | // ____________________ 379 | // |____________________| 380 | // 381 | // into 382 | // 383 | // | | 384 | // | ____________| 385 | // |____________| 386 | // 387 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned 388 | // 389 | // This makes BF take about 2x the time 390 | 391 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { 392 | tail = c->active_head; 393 | node = c->active_head; 394 | prev = &c->active_head; 395 | // find first node that's admissible 396 | while (tail->x < width) 397 | tail = tail->next; 398 | while (tail) { 399 | int xpos = tail->x - width; 400 | int y,waste; 401 | STBRP_ASSERT(xpos >= 0); 402 | // find the left position that matches this 403 | while (node->next->x <= xpos) { 404 | prev = &node->next; 405 | node = node->next; 406 | } 407 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); 408 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); 409 | if (y + height < c->height) { 410 | if (y <= best_y) { 411 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 412 | best_x = xpos; 413 | STBRP_ASSERT(y <= best_y); 414 | best_y = y; 415 | best_waste = waste; 416 | best = prev; 417 | } 418 | } 419 | } 420 | tail = tail->next; 421 | } 422 | } 423 | 424 | fr.prev_link = best; 425 | fr.x = best_x; 426 | fr.y = best_y; 427 | return fr; 428 | } 429 | 430 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) 431 | { 432 | // find best position according to heuristic 433 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); 434 | stbrp_node *node, *cur; 435 | 436 | // bail if: 437 | // 1. it failed 438 | // 2. the best node doesn't fit (we don't always check this) 439 | // 3. we're out of memory 440 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { 441 | res.prev_link = NULL; 442 | return res; 443 | } 444 | 445 | // on success, create new node 446 | node = context->free_head; 447 | node->x = (stbrp_coord) res.x; 448 | node->y = (stbrp_coord) (res.y + height); 449 | 450 | context->free_head = node->next; 451 | 452 | // insert the new node into the right starting point, and 453 | // let 'cur' point to the remaining nodes needing to be 454 | // stiched back in 455 | 456 | cur = *res.prev_link; 457 | if (cur->x < res.x) { 458 | // preserve the existing one, so start testing with the next one 459 | stbrp_node *next = cur->next; 460 | cur->next = node; 461 | cur = next; 462 | } else { 463 | *res.prev_link = node; 464 | } 465 | 466 | // from here, traverse cur and free the nodes, until we get to one 467 | // that shouldn't be freed 468 | while (cur->next && cur->next->x <= res.x + width) { 469 | stbrp_node *next = cur->next; 470 | // move the current node to the free list 471 | cur->next = context->free_head; 472 | context->free_head = cur; 473 | cur = next; 474 | } 475 | 476 | // stitch the list back in 477 | node->next = cur; 478 | 479 | if (cur->x < res.x + width) 480 | cur->x = (stbrp_coord) (res.x + width); 481 | 482 | #ifdef _DEBUG 483 | cur = context->active_head; 484 | while (cur->x < context->width) { 485 | STBRP_ASSERT(cur->x < cur->next->x); 486 | cur = cur->next; 487 | } 488 | STBRP_ASSERT(cur->next == NULL); 489 | 490 | { 491 | stbrp_node *L1 = NULL, *L2 = NULL; 492 | int count=0; 493 | cur = context->active_head; 494 | while (cur) { 495 | L1 = cur; 496 | cur = cur->next; 497 | ++count; 498 | } 499 | cur = context->free_head; 500 | while (cur) { 501 | L2 = cur; 502 | cur = cur->next; 503 | ++count; 504 | } 505 | STBRP_ASSERT(count == context->num_nodes+2); 506 | } 507 | #endif 508 | 509 | return res; 510 | } 511 | 512 | static int rect_height_compare(const void *a, const void *b) 513 | { 514 | const stbrp_rect *p = (const stbrp_rect *) a; 515 | const stbrp_rect *q = (const stbrp_rect *) b; 516 | if (p->h > q->h) 517 | return -1; 518 | if (p->h < q->h) 519 | return 1; 520 | return (p->w > q->w) ? -1 : (p->w < q->w); 521 | } 522 | 523 | static int rect_width_compare(const void *a, const void *b) 524 | { 525 | const stbrp_rect *p = (const stbrp_rect *) a; 526 | const stbrp_rect *q = (const stbrp_rect *) b; 527 | if (p->w > q->w) 528 | return -1; 529 | if (p->w < q->w) 530 | return 1; 531 | return (p->h > q->h) ? -1 : (p->h < q->h); 532 | } 533 | 534 | static int rect_original_order(const void *a, const void *b) 535 | { 536 | const stbrp_rect *p = (const stbrp_rect *) a; 537 | const stbrp_rect *q = (const stbrp_rect *) b; 538 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 539 | } 540 | 541 | #ifdef STBRP_LARGE_RECTS 542 | #define STBRP__MAXVAL 0xffffffff 543 | #else 544 | #define STBRP__MAXVAL 0xffff 545 | #endif 546 | 547 | STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) 548 | { 549 | int i; 550 | 551 | // we use the 'was_packed' field internally to allow sorting/unsorting 552 | for (i=0; i < num_rects; ++i) { 553 | rects[i].was_packed = i; 554 | #ifndef STBRP_LARGE_RECTS 555 | STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff); 556 | #endif 557 | } 558 | 559 | // sort according to heuristic 560 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); 561 | 562 | for (i=0; i < num_rects; ++i) { 563 | if (rects[i].w == 0 || rects[i].h == 0) { 564 | rects[i].x = rects[i].y = 0; // empty rect needs no space 565 | } else { 566 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 567 | if (fr.prev_link) { 568 | rects[i].x = (stbrp_coord) fr.x; 569 | rects[i].y = (stbrp_coord) fr.y; 570 | } else { 571 | rects[i].x = rects[i].y = STBRP__MAXVAL; 572 | } 573 | } 574 | } 575 | 576 | // unsort 577 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); 578 | 579 | // set was_packed flags 580 | for (i=0; i < num_rects; ++i) 581 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); 582 | } 583 | #endif 584 | -------------------------------------------------------------------------------- /imgui/src/imgui_impl_glfw.cpp: -------------------------------------------------------------------------------- 1 | // ImGui GLFW binding with OpenGL (legacy, fixed pipeline) 2 | // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. 3 | // (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) 4 | 5 | // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** 6 | // **Prefer using the code in the opengl3_example/ folder** 7 | // This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read. 8 | // If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more 9 | // complicated, will require your code to reset every single OpenGL attributes to their initial state, and might 10 | // confuse your GPU driver. 11 | // The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API. 12 | 13 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 14 | // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). 15 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 16 | // https://github.com/ocornut/imgui 17 | 18 | #include 19 | #include "imgui_impl_glfw.h" 20 | 21 | // GLFW 22 | #include 23 | #ifdef _WIN32 24 | #undef APIENTRY 25 | #define GLFW_EXPOSE_NATIVE_WIN32 26 | #define GLFW_EXPOSE_NATIVE_WGL 27 | #include 28 | #endif 29 | 30 | // Data 31 | static GLFWwindow* g_Window = NULL; 32 | static double g_Time = 0.0f; 33 | static bool g_MouseJustPressed[3] = { false, false, false }; 34 | static float g_MouseWheel = 0.0f; 35 | static GLuint g_FontTexture = 0; 36 | 37 | // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) 38 | void ImGui_ImplGlfwGL2_RenderDrawLists(ImDrawData* draw_data) 39 | // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. 40 | // If text or lines are blurry when integrating ImGui in your engine: in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) 41 | { 42 | // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) 43 | ImGuiIO& io = ImGui::GetIO(); 44 | int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); 45 | int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); 46 | if (fb_width == 0 || fb_height == 0) 47 | return; 48 | draw_data->ScaleClipRects(io.DisplayFramebufferScale); 49 | 50 | // We are using the OpenGL fixed pipeline to make the example code simpler to read! 51 | // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill. 52 | GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); 53 | GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); 54 | GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); 55 | GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); 56 | glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); 57 | glEnable(GL_BLEND); 58 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 59 | glDisable(GL_CULL_FACE); 60 | glDisable(GL_DEPTH_TEST); 61 | glEnable(GL_SCISSOR_TEST); 62 | glEnableClientState(GL_VERTEX_ARRAY); 63 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); 64 | glEnableClientState(GL_COLOR_ARRAY); 65 | glEnable(GL_TEXTURE_2D); 66 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 67 | //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound 68 | 69 | // Setup viewport, orthographic projection matrix 70 | glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); 71 | glMatrixMode(GL_PROJECTION); 72 | glPushMatrix(); 73 | glLoadIdentity(); 74 | glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f); 75 | glMatrixMode(GL_MODELVIEW); 76 | glPushMatrix(); 77 | glLoadIdentity(); 78 | 79 | // Render command lists 80 | #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) 81 | for (int n = 0; n < draw_data->CmdListsCount; n++) 82 | { 83 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 84 | const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; 85 | const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; 86 | glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos))); 87 | glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, uv))); 88 | glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, col))); 89 | 90 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 91 | { 92 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 93 | if (pcmd->UserCallback) 94 | { 95 | pcmd->UserCallback(cmd_list, pcmd); 96 | } 97 | else 98 | { 99 | glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); 100 | glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); 101 | glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer); 102 | } 103 | idx_buffer += pcmd->ElemCount; 104 | } 105 | } 106 | #undef OFFSETOF 107 | 108 | // Restore modified state 109 | glDisableClientState(GL_COLOR_ARRAY); 110 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); 111 | glDisableClientState(GL_VERTEX_ARRAY); 112 | glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture); 113 | glMatrixMode(GL_MODELVIEW); 114 | glPopMatrix(); 115 | glMatrixMode(GL_PROJECTION); 116 | glPopMatrix(); 117 | glPopAttrib(); 118 | glPolygonMode(GL_FRONT, last_polygon_mode[0]); glPolygonMode(GL_BACK, last_polygon_mode[1]); 119 | glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); 120 | glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); 121 | } 122 | 123 | static const char* ImGui_ImplGlfwGL2_GetClipboardText(void* user_data) 124 | { 125 | return glfwGetClipboardString((GLFWwindow*)user_data); 126 | } 127 | 128 | static void ImGui_ImplGlfwGL2_SetClipboardText(void* user_data, const char* text) 129 | { 130 | glfwSetClipboardString((GLFWwindow*)user_data, text); 131 | } 132 | 133 | void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) 134 | { 135 | if (action == GLFW_PRESS && button >= 0 && button < 3) 136 | g_MouseJustPressed[button] = true; 137 | } 138 | 139 | void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) 140 | { 141 | g_MouseWheel += (float)yoffset; // Use fractional mouse wheel. 142 | } 143 | 144 | void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mods) 145 | { 146 | ImGuiIO& io = ImGui::GetIO(); 147 | if (action == GLFW_PRESS) 148 | io.KeysDown[key] = true; 149 | if (action == GLFW_RELEASE) 150 | io.KeysDown[key] = false; 151 | 152 | (void)mods; // Modifiers are not reliable across systems 153 | io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; 154 | io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; 155 | io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; 156 | io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; 157 | } 158 | 159 | void ImGui_ImplGlfwGL2_CharCallback(GLFWwindow*, unsigned int c) 160 | { 161 | ImGuiIO& io = ImGui::GetIO(); 162 | if (c > 0 && c < 0x10000) 163 | io.AddInputCharacter((unsigned short)c); 164 | } 165 | 166 | bool ImGui_ImplGlfwGL2_CreateDeviceObjects() 167 | { 168 | // Build texture atlas 169 | ImGuiIO& io = ImGui::GetIO(); 170 | unsigned char* pixels; 171 | int width, height; 172 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. 173 | 174 | // Upload texture to graphics system 175 | GLint last_texture; 176 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); 177 | glGenTextures(1, &g_FontTexture); 178 | glBindTexture(GL_TEXTURE_2D, g_FontTexture); 179 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 180 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 181 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 182 | 183 | // Store our identifier 184 | io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; 185 | 186 | // Restore state 187 | glBindTexture(GL_TEXTURE_2D, last_texture); 188 | 189 | return true; 190 | } 191 | 192 | void ImGui_ImplGlfwGL2_InvalidateDeviceObjects() 193 | { 194 | if (g_FontTexture) 195 | { 196 | glDeleteTextures(1, &g_FontTexture); 197 | ImGui::GetIO().Fonts->TexID = 0; 198 | g_FontTexture = 0; 199 | } 200 | } 201 | 202 | bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) 203 | { 204 | g_Window = window; 205 | 206 | ImGuiIO& io = ImGui::GetIO(); 207 | io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. 208 | io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; 209 | io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; 210 | io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; 211 | io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; 212 | io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; 213 | io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; 214 | io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; 215 | io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; 216 | io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; 217 | io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; 218 | io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; 219 | io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; 220 | io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; 221 | io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; 222 | io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; 223 | io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; 224 | io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; 225 | io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; 226 | 227 | io.RenderDrawListsFn = ImGui_ImplGlfwGL2_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. 228 | io.SetClipboardTextFn = ImGui_ImplGlfwGL2_SetClipboardText; 229 | io.GetClipboardTextFn = ImGui_ImplGlfwGL2_GetClipboardText; 230 | io.ClipboardUserData = g_Window; 231 | #ifdef _WIN32 232 | io.ImeWindowHandle = glfwGetWin32Window(g_Window); 233 | #endif 234 | 235 | if (install_callbacks) 236 | { 237 | glfwSetMouseButtonCallback(window, ImGui_ImplGlfwGL2_MouseButtonCallback); 238 | glfwSetScrollCallback(window, ImGui_ImplGlfwGL2_ScrollCallback); 239 | glfwSetKeyCallback(window, ImGui_ImplGlfwGL2_KeyCallback); 240 | glfwSetCharCallback(window, ImGui_ImplGlfwGL2_CharCallback); 241 | } 242 | 243 | return true; 244 | } 245 | 246 | void ImGui_ImplGlfwGL2_Shutdown() 247 | { 248 | ImGui_ImplGlfwGL2_InvalidateDeviceObjects(); 249 | ImGui::Shutdown(); 250 | } 251 | 252 | void ImGui_ImplGlfwGL2_NewFrame() 253 | { 254 | if (!g_FontTexture) 255 | ImGui_ImplGlfwGL2_CreateDeviceObjects(); 256 | 257 | ImGuiIO& io = ImGui::GetIO(); 258 | 259 | // Setup display size (every frame to accommodate for window resizing) 260 | int w, h; 261 | int display_w, display_h; 262 | glfwGetWindowSize(g_Window, &w, &h); 263 | glfwGetFramebufferSize(g_Window, &display_w, &display_h); 264 | io.DisplaySize = ImVec2((float)w, (float)h); 265 | io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); 266 | 267 | // Setup time step 268 | double current_time = glfwGetTime(); 269 | io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); 270 | g_Time = current_time; 271 | 272 | // Setup inputs 273 | // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) 274 | if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) 275 | { 276 | if (io.WantMoveMouse) 277 | { 278 | glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y); // Set mouse position if requested by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) 279 | } 280 | else 281 | { 282 | double mouse_x, mouse_y; 283 | glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); 284 | io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Get mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) 285 | } 286 | } 287 | else 288 | { 289 | io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX); 290 | } 291 | 292 | for (int i = 0; i < 3; i++) 293 | { 294 | // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. 295 | io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0; 296 | g_MouseJustPressed[i] = false; 297 | } 298 | 299 | io.MouseWheel = g_MouseWheel; 300 | g_MouseWheel = 0.0f; 301 | 302 | // Hide OS mouse cursor if ImGui is drawing it 303 | glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); 304 | 305 | // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. 306 | ImGui::NewFrame(); 307 | } 308 | -------------------------------------------------------------------------------- /imgui/src/imgui_impl_sdl.cpp: -------------------------------------------------------------------------------- 1 | // ImGui SDL2 binding with OpenGL (legacy, fixed pipeline) 2 | // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. 3 | // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) 4 | 5 | // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** 6 | // **Prefer using the code in the sdl_opengl3_example/ folder** 7 | // This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read. 8 | // If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more 9 | // complicated, will require your code to reset every single OpenGL attributes to their initial state, and might 10 | // confuse your GPU driver. 11 | // The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API. 12 | 13 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 14 | // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). 15 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 16 | // https://github.com/ocornut/imgui 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "imgui_impl_sdl.h" 23 | 24 | // Data 25 | static double g_Time = 0.0f; 26 | static bool g_MousePressed[3] = { false, false, false }; 27 | static float g_MouseWheel = 0.0f; 28 | static GLuint g_FontTexture = 0; 29 | 30 | // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) 31 | // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. 32 | // If text or lines are blurry when integrating ImGui in your engine: in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) 33 | void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data) 34 | { 35 | // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) 36 | ImGuiIO& io = ImGui::GetIO(); 37 | int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); 38 | int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); 39 | if (fb_width == 0 || fb_height == 0) 40 | return; 41 | draw_data->ScaleClipRects(io.DisplayFramebufferScale); 42 | 43 | // We are using the OpenGL fixed pipeline to make the example code simpler to read! 44 | // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill. 45 | GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); 46 | GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); 47 | GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); 48 | GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); 49 | glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); 50 | glEnable(GL_BLEND); 51 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 52 | glDisable(GL_CULL_FACE); 53 | glDisable(GL_DEPTH_TEST); 54 | glEnable(GL_SCISSOR_TEST); 55 | glEnableClientState(GL_VERTEX_ARRAY); 56 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); 57 | glEnableClientState(GL_COLOR_ARRAY); 58 | glEnable(GL_TEXTURE_2D); 59 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 60 | //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound 61 | 62 | // Setup viewport, orthographic projection matrix 63 | glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); 64 | glMatrixMode(GL_PROJECTION); 65 | glPushMatrix(); 66 | glLoadIdentity(); 67 | glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f); 68 | glMatrixMode(GL_MODELVIEW); 69 | glPushMatrix(); 70 | glLoadIdentity(); 71 | 72 | // Render command lists 73 | #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) 74 | for (int n = 0; n < draw_data->CmdListsCount; n++) 75 | { 76 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 77 | const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; 78 | const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; 79 | glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos))); 80 | glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, uv))); 81 | glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, col))); 82 | 83 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 84 | { 85 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 86 | if (pcmd->UserCallback) 87 | { 88 | pcmd->UserCallback(cmd_list, pcmd); 89 | } 90 | else 91 | { 92 | glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); 93 | glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); 94 | glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer); 95 | } 96 | idx_buffer += pcmd->ElemCount; 97 | } 98 | } 99 | #undef OFFSETOF 100 | 101 | // Restore modified state 102 | glDisableClientState(GL_COLOR_ARRAY); 103 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); 104 | glDisableClientState(GL_VERTEX_ARRAY); 105 | glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture); 106 | glMatrixMode(GL_MODELVIEW); 107 | glPopMatrix(); 108 | glMatrixMode(GL_PROJECTION); 109 | glPopMatrix(); 110 | glPopAttrib(); 111 | glPolygonMode(GL_FRONT, last_polygon_mode[0]); glPolygonMode(GL_BACK, last_polygon_mode[1]); 112 | glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); 113 | glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); 114 | } 115 | 116 | static const char* ImGui_ImplSdl_GetClipboardText(void*) 117 | { 118 | return SDL_GetClipboardText(); 119 | } 120 | 121 | static void ImGui_ImplSdl_SetClipboardText(void*, const char* text) 122 | { 123 | SDL_SetClipboardText(text); 124 | } 125 | 126 | // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. 127 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. 128 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. 129 | // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. 130 | bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event) 131 | { 132 | ImGuiIO& io = ImGui::GetIO(); 133 | switch (event->type) 134 | { 135 | case SDL_MOUSEWHEEL: 136 | { 137 | if (event->wheel.y > 0) 138 | g_MouseWheel = 1; 139 | if (event->wheel.y < 0) 140 | g_MouseWheel = -1; 141 | return true; 142 | } 143 | case SDL_MOUSEBUTTONDOWN: 144 | { 145 | if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true; 146 | if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true; 147 | if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true; 148 | return true; 149 | } 150 | case SDL_TEXTINPUT: 151 | { 152 | io.AddInputCharactersUTF8(event->text.text); 153 | return true; 154 | } 155 | case SDL_KEYDOWN: 156 | case SDL_KEYUP: 157 | { 158 | int key = event->key.keysym.sym & ~SDLK_SCANCODE_MASK; 159 | io.KeysDown[key] = (event->type == SDL_KEYDOWN); 160 | io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); 161 | io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); 162 | io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0); 163 | io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0); 164 | return true; 165 | } 166 | } 167 | return false; 168 | } 169 | 170 | bool ImGui_ImplSdlGL2_CreateDeviceObjects() 171 | { 172 | // Build texture atlas 173 | ImGuiIO& io = ImGui::GetIO(); 174 | unsigned char* pixels; 175 | int width, height; 176 | io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); 177 | 178 | // Upload texture to graphics system 179 | GLint last_texture; 180 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); 181 | glGenTextures(1, &g_FontTexture); 182 | glBindTexture(GL_TEXTURE_2D, g_FontTexture); 183 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 184 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 185 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 186 | glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); 187 | 188 | // Store our identifier 189 | io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; 190 | 191 | // Restore state 192 | glBindTexture(GL_TEXTURE_2D, last_texture); 193 | 194 | return true; 195 | } 196 | 197 | void ImGui_ImplSdlGL2_InvalidateDeviceObjects() 198 | { 199 | if (g_FontTexture) 200 | { 201 | glDeleteTextures(1, &g_FontTexture); 202 | ImGui::GetIO().Fonts->TexID = 0; 203 | g_FontTexture = 0; 204 | } 205 | } 206 | 207 | bool ImGui_ImplSdlGL2_Init(SDL_Window* window) 208 | { 209 | ImGuiIO& io = ImGui::GetIO(); 210 | io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. 211 | io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; 212 | io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; 213 | io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP; 214 | io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN; 215 | io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP; 216 | io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; 217 | io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; 218 | io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; 219 | io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; 220 | io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; 221 | io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; 222 | io.KeyMap[ImGuiKey_Escape] = SDLK_ESCAPE; 223 | io.KeyMap[ImGuiKey_A] = SDLK_a; 224 | io.KeyMap[ImGuiKey_C] = SDLK_c; 225 | io.KeyMap[ImGuiKey_V] = SDLK_v; 226 | io.KeyMap[ImGuiKey_X] = SDLK_x; 227 | io.KeyMap[ImGuiKey_Y] = SDLK_y; 228 | io.KeyMap[ImGuiKey_Z] = SDLK_z; 229 | 230 | io.RenderDrawListsFn = ImGui_ImplSdl_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. 231 | io.SetClipboardTextFn = ImGui_ImplSdl_SetClipboardText; 232 | io.GetClipboardTextFn = ImGui_ImplSdl_GetClipboardText; 233 | io.ClipboardUserData = NULL; 234 | 235 | #ifdef _WIN32 236 | SDL_SysWMinfo wmInfo; 237 | SDL_VERSION(&wmInfo.version); 238 | SDL_GetWindowWMInfo(window, &wmInfo); 239 | io.ImeWindowHandle = wmInfo.info.win.window; 240 | #else 241 | (void)window; 242 | #endif 243 | 244 | return true; 245 | } 246 | 247 | void ImGui_ImplSdlGL2_Shutdown() 248 | { 249 | ImGui_ImplSdlGL2_InvalidateDeviceObjects(); 250 | ImGui::Shutdown(); 251 | } 252 | 253 | void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) 254 | { 255 | if (!g_FontTexture) 256 | ImGui_ImplSdlGL2_CreateDeviceObjects(); 257 | 258 | ImGuiIO& io = ImGui::GetIO(); 259 | 260 | // Setup display size (every frame to accommodate for window resizing) 261 | int w, h; 262 | int display_w, display_h; 263 | SDL_GetWindowSize(window, &w, &h); 264 | SDL_GL_GetDrawableSize(window, &display_w, &display_h); 265 | io.DisplaySize = ImVec2((float)w, (float)h); 266 | io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); 267 | 268 | // Setup time step 269 | Uint32 time = SDL_GetTicks(); 270 | double current_time = time / 1000.0; 271 | io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); 272 | g_Time = current_time; 273 | 274 | // Setup inputs 275 | // (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent()) 276 | int mx, my; 277 | Uint32 mouseMask = SDL_GetMouseState(&mx, &my); 278 | if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS) 279 | io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) 280 | else 281 | io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX); 282 | 283 | io.MouseDown[0] = g_MousePressed[0] || (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. 284 | io.MouseDown[1] = g_MousePressed[1] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; 285 | io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; 286 | g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; 287 | 288 | io.MouseWheel = g_MouseWheel; 289 | g_MouseWheel = 0.0f; 290 | 291 | // Hide OS mouse cursor if ImGui is drawing it 292 | SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); 293 | 294 | // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. 295 | ImGui::NewFrame(); 296 | } 297 | -------------------------------------------------------------------------------- /imgui/src/main.cpp: -------------------------------------------------------------------------------- 1 | // ImGui - standalone example application for GLFW + OpenGL2, using legacy fixed pipeline 2 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 3 | // (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) 4 | 5 | // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** 6 | // **Prefer using the code in the opengl3_example/ folder** 7 | // See imgui_impl_glfw.cpp for details. 8 | 9 | #include 10 | #include "imgui_impl_glfw.h" 11 | #include 12 | #include 13 | 14 | static void error_callback(int error, const char* description) 15 | { 16 | fprintf(stderr, "Error %d: %s\n", error, description); 17 | } 18 | 19 | int main(int, char**) 20 | { 21 | // Setup window 22 | glfwSetErrorCallback(error_callback); 23 | if (!glfwInit()) 24 | return 1; 25 | GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL2 example", NULL, NULL); 26 | glfwMakeContextCurrent(window); 27 | glfwSwapInterval(1); // Enable vsync 28 | 29 | // Setup ImGui binding 30 | ImGui_ImplGlfwGL2_Init(window, true); 31 | 32 | // Setup style 33 | ImGui::StyleColorsClassic(); 34 | //ImGui::StyleColorsDark(); 35 | 36 | // Load Fonts 37 | // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. 38 | // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. 39 | // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). 40 | // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. 41 | // - Read 'extra_fonts/README.txt' for more instructions and details. 42 | // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! 43 | //ImGuiIO& io = ImGui::GetIO(); 44 | //io.Fonts->AddFontDefault(); 45 | //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); 46 | //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); 47 | //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); 48 | //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); 49 | //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); 50 | //IM_ASSERT(font != NULL); 51 | 52 | bool show_demo_window = true; 53 | bool show_another_window = false; 54 | ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); 55 | 56 | // Main loop 57 | while (!glfwWindowShouldClose(window)) 58 | { 59 | // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. 60 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. 61 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. 62 | // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. 63 | glfwPollEvents(); 64 | ImGui_ImplGlfwGL2_NewFrame(); 65 | 66 | // 1. Show a simple window. 67 | // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". 68 | { 69 | static float f = 0.0f; 70 | ImGui::Text("Hello, world!"); // Some text (you can use a format string too) 71 | ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f 72 | ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color 73 | if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. 74 | show_demo_window ^= 1; 75 | if (ImGui::Button("Another Window")) 76 | show_another_window ^= 1; 77 | ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); 78 | } 79 | 80 | // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. 81 | if (show_another_window) 82 | { 83 | ImGui::Begin("Another Window", &show_another_window); 84 | ImGui::Text("Hello from another window!"); 85 | ImGui::End(); 86 | } 87 | 88 | // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). 89 | if (show_demo_window) 90 | { 91 | ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! 92 | ImGui::ShowDemoWindow(&show_demo_window); 93 | } 94 | 95 | // Rendering 96 | int display_w, display_h; 97 | glfwGetFramebufferSize(window, &display_w, &display_h); 98 | glViewport(0, 0, display_w, display_h); 99 | glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); 100 | glClear(GL_COLOR_BUFFER_BIT); 101 | //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound, but prefer using the GL3+ code. 102 | ImGui::Render(); 103 | glfwSwapBuffers(window); 104 | } 105 | 106 | // Cleanup 107 | ImGui_ImplGlfwGL2_Shutdown(); 108 | glfwTerminate(); 109 | 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /imgui/src/main_sdl.cpp: -------------------------------------------------------------------------------- 1 | // ImGui - standalone example application for SDL2 + OpenGL 2 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 3 | // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) 4 | 5 | // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** 6 | // **Prefer using the code in the sdl_opengl3_example/ folder** 7 | // See imgui_impl_sdl.cpp for details. 8 | 9 | #include 10 | #include "imgui_impl_sdl.h" 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int, char**) 16 | { 17 | // Setup SDL 18 | if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) 19 | { 20 | printf("Error: %s\n", SDL_GetError()); 21 | return -1; 22 | } 23 | 24 | // Setup window 25 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 26 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 27 | SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); 28 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); 29 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); 30 | SDL_DisplayMode current; 31 | SDL_GetCurrentDisplayMode(0, ¤t); 32 | SDL_Window *window = SDL_CreateWindow("ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); 33 | SDL_GLContext glcontext = SDL_GL_CreateContext(window); 34 | 35 | // Setup ImGui binding 36 | ImGui_ImplSdlGL2_Init(window); 37 | 38 | // Setup style 39 | ImGui::StyleColorsClassic(); 40 | //ImGui::StyleColorsDark(); 41 | 42 | // Load Fonts 43 | // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. 44 | // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. 45 | // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). 46 | // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. 47 | // - Read 'extra_fonts/README.txt' for more instructions and details. 48 | // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! 49 | //ImGuiIO& io = ImGui::GetIO(); 50 | //io.Fonts->AddFontDefault(); 51 | //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); 52 | //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); 53 | //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); 54 | //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); 55 | //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); 56 | //IM_ASSERT(font != NULL); 57 | 58 | bool show_demo_window = true; 59 | bool show_another_window = false; 60 | ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); 61 | 62 | // Main loop 63 | bool done = false; 64 | while (!done) 65 | { 66 | // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. 67 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. 68 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. 69 | // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. 70 | SDL_Event event; 71 | while (SDL_PollEvent(&event)) 72 | { 73 | ImGui_ImplSdlGL2_ProcessEvent(&event); 74 | if (event.type == SDL_QUIT) 75 | done = true; 76 | } 77 | ImGui_ImplSdlGL2_NewFrame(window); 78 | 79 | // 1. Show a simple window 80 | // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". 81 | { 82 | static float f = 0.0f; 83 | ImGui::Text("Hello, world!"); // Some text (you can use a format string too) 84 | ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f 85 | ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color 86 | if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. 87 | show_demo_window ^= 1; 88 | if (ImGui::Button("Another Window")) 89 | show_another_window ^= 1; 90 | ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); 91 | } 92 | 93 | // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. 94 | if (show_another_window) 95 | { 96 | ImGui::Begin("Another Window", &show_another_window); 97 | ImGui::Text("Hello from another window!"); 98 | ImGui::End(); 99 | } 100 | 101 | // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). 102 | if (show_demo_window) 103 | { 104 | ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! 105 | ImGui::ShowDemoWindow(&show_demo_window); 106 | } 107 | 108 | // Rendering 109 | glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y); 110 | glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); 111 | glClear(GL_COLOR_BUFFER_BIT); 112 | //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound 113 | ImGui::Render(); 114 | SDL_GL_SwapWindow(window); 115 | } 116 | 117 | // Cleanup 118 | ImGui_ImplSdlGL2_Shutdown(); 119 | SDL_GL_DeleteContext(glcontext); 120 | SDL_DestroyWindow(window); 121 | SDL_Quit(); 122 | 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /minizip/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(test_minizip) 3 | 4 | find_package(ZLIB) 5 | find_package(PkgConfig) 6 | pkg_check_modules(UNZIP minizip) 7 | 8 | include_directories(include 9 | ${UNZIP_INCLUDEDIR} 10 | ) 11 | 12 | find_library(minizip_LIBRARY minizip) 13 | 14 | add_executable(minizip 15 | src/minizip.c 16 | ) 17 | 18 | add_executable(miniunzip 19 | src/miniunzip.c 20 | ) 21 | 22 | target_link_libraries(minizip 23 | ${ZLIB_LIBRARIES} 24 | ${minizip_LIBRARY} 25 | ) 26 | 27 | target_link_libraries(miniunzip 28 | ${ZLIB_LIBRARIES} 29 | ${minizip_LIBRARY} 30 | ) 31 | -------------------------------------------------------------------------------- /minizip/README.md: -------------------------------------------------------------------------------- 1 | # Minizip 2 | [Minizip](http://www.winimage.com/zLibDll/minizip.html) is a simple ZIP-file library, using zlib. zlib is part of almost every OS distribution, while minizip is not. Unlike other CMake-ready libraries, Minizip packages come with pkg-config files, so the `find_package` call will not work. Here we show how to use pkg-config from CMake, along with why it's not preferred. 3 | 4 | ## Requirements 5 | 6 | Linux: 7 | - zlib1g-dev 8 | - libminizip-dev 9 | 10 | OSX/BSD: 11 | - minizip 12 | - zlib 13 | 14 | ## Project layout 15 | 16 | ``` 17 | minizip 18 | |-- CMakeLists.txt 19 | |-- README.md 20 | `-- src 21 | |-- miniunzip.c 22 | `-- minizip.c 23 | ``` 24 | 25 | ## CMakeLists walkthrough 26 | Define our project and CMake version. Versions prior to 3.1 can have random bugs when dealing directly with pkg-config, so we enforce the minimum version here. 27 | ``` 28 | cmake_minimum_required(VERSION 3.1) 29 | project(test_minizip) 30 | ``` 31 | 32 | CMake ships a FindZLIB.cmake file, so request it here. As a potential quirk, note that `find_package(zlib)` would also work on OSX/BSD systems, but not on Linux, as it's case-sensitive. It's safer just to request the uppercase version to avoid confusion. 33 | ``` 34 | find_package(ZLIB) 35 | ``` 36 | 37 | Since we know we are going to need pkg-config, request the built-in PkgConfig CMake package 38 | ``` 39 | find_package(PkgConfig) 40 | ``` 41 | There are two major ways to find pkg-config modules: `pkg_search_module`, and `pkg_check_modules`. They have slightly differing syntaxes. I prefer to use `pkg_check_modules` to enforce the requirement. 42 | ``` 43 | pkg_check_modules(UNZIP minizip) 44 | ``` 45 | 46 | Because we called `pkg_check_modules` with a prefix(`UNZIP`), the minizip variables will be bound to that prefix. (Look in `/CMakeCache.txt` to see them all, searching for "UNZIP_") 47 | 48 | As usual, include minizip/include directory, and the directory specified by the minizip pkg-config 49 | ``` 50 | include_directories(include 51 | ${UNZIP_INCLUDEDIR} 52 | ) 53 | ``` 54 | 55 | Since we didn't use `find_package`, we have to include the actual library flags manually, which is what `find_library` is for. `find_package` will automatically do this and bind the flags to `_LIBRARIES`, which is another good reason to prefer `find_package`. 56 | ``` 57 | find_library(minizip_LIBRARY minizip) 58 | ``` 59 | 60 | Now we can add our executables. We have two separate source files which compile to an executable each: minizip, and miniunzip. 61 | ``` 62 | add_executable(minizip 63 | src/minizip.c 64 | ) 65 | add_executable(miniunzip 66 | src/miniunzip.c 67 | ) 68 | ``` 69 | 70 | Each executable needs to be linked separately. Note that by using `find_library` the minizip flags are now in the `minizip_LIBRARY` variable, as opposed to zlib which gets a \_LIBRARIES suffix(again, thanks to `find_package`). 71 | ``` 72 | target_link_libraries(minizip 73 | ${ZLIB_LIBRARIES} 74 | ${minizip_LIBRARY} 75 | ) 76 | target_link_libraries(miniunzip 77 | ${ZLIB_LIBRARIES} 78 | ${minizip_LIBRARY} 79 | ) 80 | ``` 81 | 82 | ## Use 83 | Let's make our build dir and run cmake like usual: 84 | ``` 85 | $ mkdir build 86 | $ cd build 87 | $ cmake .. 88 | ``` 89 | 90 | After the usual compiler detection, you should see this output: 91 | ``` 92 | -- Found ZLIB: /usr/lib/libz.so.5.0 (found version "1.2.3") 93 | -- Found PkgConfig: /usr/bin/pkg-config (found version "0.27.1") 94 | -- Checking for module 'minizip' 95 | -- Found minizip, version 1.2.11 96 | ``` 97 | (location and version numbers will vary on your system) 98 | 99 | Then we can execute: 100 | ``` 101 | $ make 102 | $ minizip test.zip ../src/minizip.c 103 | $ file test.zip 104 | ``` 105 | -------------------------------------------------------------------------------- /minizip/src/miniunzip.c: -------------------------------------------------------------------------------- 1 | /* 2 | miniunz.c 3 | Version 1.1, February 14h, 2010 4 | sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) 5 | 6 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) 7 | 8 | Modifications of Unzip for Zip64 9 | Copyright (C) 2007-2008 Even Rouault 10 | 11 | Modifications for Zip64 support on both zip and unzip 12 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) 13 | */ 14 | 15 | #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) 16 | #ifndef __USE_FILE_OFFSET64 17 | #define __USE_FILE_OFFSET64 18 | #endif 19 | #ifndef __USE_LARGEFILE64 20 | #define __USE_LARGEFILE64 21 | #endif 22 | #ifndef _LARGEFILE64_SOURCE 23 | #define _LARGEFILE64_SOURCE 24 | #endif 25 | #ifndef _FILE_OFFSET_BIT 26 | #define _FILE_OFFSET_BIT 64 27 | #endif 28 | #endif 29 | 30 | #ifdef __APPLE__ 31 | // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions 32 | #define FOPEN_FUNC(filename, mode) fopen(filename, mode) 33 | #define FTELLO_FUNC(stream) ftello(stream) 34 | #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) 35 | #else 36 | #define FOPEN_FUNC(filename, mode) fopen64(filename, mode) 37 | #define FTELLO_FUNC(stream) ftello64(stream) 38 | #define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) 39 | #endif 40 | 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #ifdef _WIN32 50 | # include 51 | # include 52 | #else 53 | # include 54 | # include 55 | #endif 56 | 57 | 58 | #include "unzip.h" 59 | 60 | #define CASESENSITIVITY (0) 61 | #define WRITEBUFFERSIZE (8192) 62 | #define MAXFILENAME (256) 63 | 64 | #ifdef _WIN32 65 | #define USEWIN32IOAPI 66 | #include "iowin32.h" 67 | #endif 68 | /* 69 | mini unzip, demo of unzip package 70 | 71 | usage : 72 | Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] 73 | 74 | list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT 75 | if it exists 76 | */ 77 | 78 | 79 | /* change_file_date : change the date/time of a file 80 | filename : the filename of the file where date/time must be modified 81 | dosdate : the new date at the MSDos format (4 bytes) 82 | tmu_date : the SAME new date at the tm_unz format */ 83 | void change_file_date(filename,dosdate,tmu_date) 84 | const char *filename; 85 | uLong dosdate; 86 | tm_unz tmu_date; 87 | { 88 | #ifdef _WIN32 89 | HANDLE hFile; 90 | FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; 91 | 92 | hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE, 93 | 0,NULL,OPEN_EXISTING,0,NULL); 94 | GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); 95 | DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); 96 | LocalFileTimeToFileTime(&ftLocal,&ftm); 97 | SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); 98 | CloseHandle(hFile); 99 | #else 100 | #ifdef unix || __APPLE__ 101 | struct utimbuf ut; 102 | struct tm newdate; 103 | newdate.tm_sec = tmu_date.tm_sec; 104 | newdate.tm_min=tmu_date.tm_min; 105 | newdate.tm_hour=tmu_date.tm_hour; 106 | newdate.tm_mday=tmu_date.tm_mday; 107 | newdate.tm_mon=tmu_date.tm_mon; 108 | if (tmu_date.tm_year > 1900) 109 | newdate.tm_year=tmu_date.tm_year - 1900; 110 | else 111 | newdate.tm_year=tmu_date.tm_year ; 112 | newdate.tm_isdst=-1; 113 | 114 | ut.actime=ut.modtime=mktime(&newdate); 115 | utime(filename,&ut); 116 | #endif 117 | #endif 118 | } 119 | 120 | 121 | /* mymkdir and change_file_date are not 100 % portable 122 | As I don't know well Unix, I wait feedback for the unix portion */ 123 | 124 | int mymkdir(dirname) 125 | const char* dirname; 126 | { 127 | int ret=0; 128 | #ifdef _WIN32 129 | ret = _mkdir(dirname); 130 | #elif unix 131 | ret = mkdir (dirname,0775); 132 | #elif __APPLE__ 133 | ret = mkdir (dirname,0775); 134 | #endif 135 | return ret; 136 | } 137 | 138 | int makedir (newdir) 139 | char *newdir; 140 | { 141 | char *buffer ; 142 | char *p; 143 | int len = (int)strlen(newdir); 144 | 145 | if (len <= 0) 146 | return 0; 147 | 148 | buffer = (char*)malloc(len+1); 149 | if (buffer==NULL) 150 | { 151 | printf("Error allocating memory\n"); 152 | return UNZ_INTERNALERROR; 153 | } 154 | strcpy(buffer,newdir); 155 | 156 | if (buffer[len-1] == '/') { 157 | buffer[len-1] = '\0'; 158 | } 159 | if (mymkdir(buffer) == 0) 160 | { 161 | free(buffer); 162 | return 1; 163 | } 164 | 165 | p = buffer+1; 166 | while (1) 167 | { 168 | char hold; 169 | 170 | while(*p && *p != '\\' && *p != '/') 171 | p++; 172 | hold = *p; 173 | *p = 0; 174 | if ((mymkdir(buffer) == -1) && (errno == ENOENT)) 175 | { 176 | printf("couldn't create directory %s\n",buffer); 177 | free(buffer); 178 | return 0; 179 | } 180 | if (hold == 0) 181 | break; 182 | *p++ = hold; 183 | } 184 | free(buffer); 185 | return 1; 186 | } 187 | 188 | void do_banner() 189 | { 190 | printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); 191 | printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); 192 | } 193 | 194 | void do_help() 195 | { 196 | printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ 197 | " -e Extract without pathname (junk paths)\n" \ 198 | " -x Extract with pathname\n" \ 199 | " -v list files\n" \ 200 | " -l list files\n" \ 201 | " -d directory to extract into\n" \ 202 | " -o overwrite files without prompting\n" \ 203 | " -p extract crypted file using password\n\n"); 204 | } 205 | 206 | void Display64BitsSize(ZPOS64_T n, int size_char) 207 | { 208 | /* to avoid compatibility problem , we do here the conversion */ 209 | char number[21]; 210 | int offset=19; 211 | int pos_string = 19; 212 | number[20]=0; 213 | for (;;) { 214 | number[offset]=(char)((n%10)+'0'); 215 | if (number[offset] != '0') 216 | pos_string=offset; 217 | n/=10; 218 | if (offset==0) 219 | break; 220 | offset--; 221 | } 222 | { 223 | int size_display_string = 19-pos_string; 224 | while (size_char > size_display_string) 225 | { 226 | size_char--; 227 | printf(" "); 228 | } 229 | } 230 | 231 | printf("%s",&number[pos_string]); 232 | } 233 | 234 | int do_list(uf) 235 | unzFile uf; 236 | { 237 | uLong i; 238 | unz_global_info64 gi; 239 | int err; 240 | 241 | err = unzGetGlobalInfo64(uf,&gi); 242 | if (err!=UNZ_OK) 243 | printf("error %d with zipfile in unzGetGlobalInfo \n",err); 244 | printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); 245 | printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); 246 | for (i=0;i0) 260 | ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); 261 | 262 | /* display a '*' if the file is crypted */ 263 | if ((file_info.flag & 1) != 0) 264 | charCrypt='*'; 265 | 266 | if (file_info.compression_method==0) 267 | string_method="Stored"; 268 | else 269 | if (file_info.compression_method==Z_DEFLATED) 270 | { 271 | uInt iLevel=(uInt)((file_info.flag & 0x6)/2); 272 | if (iLevel==0) 273 | string_method="Defl:N"; 274 | else if (iLevel==1) 275 | string_method="Defl:X"; 276 | else if ((iLevel==2) || (iLevel==3)) 277 | string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ 278 | } 279 | else 280 | if (file_info.compression_method==Z_BZIP2ED) 281 | { 282 | string_method="BZip2 "; 283 | } 284 | else 285 | string_method="Unkn. "; 286 | 287 | Display64BitsSize(file_info.uncompressed_size,7); 288 | printf(" %6s%c",string_method,charCrypt); 289 | Display64BitsSize(file_info.compressed_size,7); 290 | printf(" %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", 291 | ratio, 292 | (uLong)file_info.tmu_date.tm_mon + 1, 293 | (uLong)file_info.tmu_date.tm_mday, 294 | (uLong)file_info.tmu_date.tm_year % 100, 295 | (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, 296 | (uLong)file_info.crc,filename_inzip); 297 | if ((i+1)='a') && (rep<='z')) 397 | rep -= 0x20; 398 | } 399 | while ((rep!='Y') && (rep!='N') && (rep!='A')); 400 | } 401 | 402 | if (rep == 'N') 403 | skip = 1; 404 | 405 | if (rep == 'A') 406 | *popt_overwrite=1; 407 | } 408 | 409 | if ((skip==0) && (err==UNZ_OK)) 410 | { 411 | fout=FOPEN_FUNC(write_filename,"wb"); 412 | /* some zipfile don't contain directory alone before file */ 413 | if ((fout==NULL) && ((*popt_extract_without_path)==0) && 414 | (filename_withoutpath!=(char*)filename_inzip)) 415 | { 416 | char c=*(filename_withoutpath-1); 417 | *(filename_withoutpath-1)='\0'; 418 | makedir(write_filename); 419 | *(filename_withoutpath-1)=c; 420 | fout=FOPEN_FUNC(write_filename,"wb"); 421 | } 422 | 423 | if (fout==NULL) 424 | { 425 | printf("error opening %s\n",write_filename); 426 | } 427 | } 428 | 429 | if (fout!=NULL) 430 | { 431 | printf(" extracting: %s\n",write_filename); 432 | 433 | do 434 | { 435 | err = unzReadCurrentFile(uf,buf,size_buf); 436 | if (err<0) 437 | { 438 | printf("error %d with zipfile in unzReadCurrentFile\n",err); 439 | break; 440 | } 441 | if (err>0) 442 | if (fwrite(buf,err,1,fout)!=1) 443 | { 444 | printf("error in writing extracted file\n"); 445 | err=UNZ_ERRNO; 446 | break; 447 | } 448 | } 449 | while (err>0); 450 | if (fout) 451 | fclose(fout); 452 | 453 | if (err==0) 454 | change_file_date(write_filename,file_info.dosDate, 455 | file_info.tmu_date); 456 | } 457 | 458 | if (err==UNZ_OK) 459 | { 460 | err = unzCloseCurrentFile (uf); 461 | if (err!=UNZ_OK) 462 | { 463 | printf("error %d with zipfile in unzCloseCurrentFile\n",err); 464 | } 465 | } 466 | else 467 | unzCloseCurrentFile(uf); /* don't lose the error */ 468 | } 469 | 470 | free(buf); 471 | return err; 472 | } 473 | 474 | 475 | int do_extract(uf,opt_extract_without_path,opt_overwrite,password) 476 | unzFile uf; 477 | int opt_extract_without_path; 478 | int opt_overwrite; 479 | const char* password; 480 | { 481 | uLong i; 482 | unz_global_info64 gi; 483 | int err; 484 | FILE* fout=NULL; 485 | 486 | err = unzGetGlobalInfo64(uf,&gi); 487 | if (err!=UNZ_OK) 488 | printf("error %d with zipfile in unzGetGlobalInfo \n",err); 489 | 490 | for (i=0;i 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | #ifdef _WIN32 52 | # include 53 | # include 54 | #else 55 | # include 56 | # include 57 | # include 58 | # include 59 | #endif 60 | 61 | #include "zip.h" 62 | 63 | #ifdef _WIN32 64 | #define USEWIN32IOAPI 65 | #include "iowin32.h" 66 | #endif 67 | 68 | 69 | 70 | #define WRITEBUFFERSIZE (16384) 71 | #define MAXFILENAME (256) 72 | 73 | #ifdef _WIN32 74 | uLong filetime(f, tmzip, dt) 75 | char *f; /* name of file to get info on */ 76 | tm_zip *tmzip; /* return value: access, modific. and creation times */ 77 | uLong *dt; /* dostime */ 78 | { 79 | int ret = 0; 80 | { 81 | FILETIME ftLocal; 82 | HANDLE hFind; 83 | WIN32_FIND_DATAA ff32; 84 | 85 | hFind = FindFirstFileA(f,&ff32); 86 | if (hFind != INVALID_HANDLE_VALUE) 87 | { 88 | FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); 89 | FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); 90 | FindClose(hFind); 91 | ret = 1; 92 | } 93 | } 94 | return ret; 95 | } 96 | #else 97 | #ifdef unix || __APPLE__ 98 | uLong filetime(f, tmzip, dt) 99 | char *f; /* name of file to get info on */ 100 | tm_zip *tmzip; /* return value: access, modific. and creation times */ 101 | uLong *dt; /* dostime */ 102 | { 103 | int ret=0; 104 | struct stat s; /* results of stat() */ 105 | struct tm* filedate; 106 | time_t tm_t=0; 107 | 108 | if (strcmp(f,"-")!=0) 109 | { 110 | char name[MAXFILENAME+1]; 111 | int len = strlen(f); 112 | if (len > MAXFILENAME) 113 | len = MAXFILENAME; 114 | 115 | strncpy(name, f,MAXFILENAME-1); 116 | /* strncpy doesnt append the trailing NULL, of the string is too long. */ 117 | name[ MAXFILENAME ] = '\0'; 118 | 119 | if (name[len - 1] == '/') 120 | name[len - 1] = '\0'; 121 | /* not all systems allow stat'ing a file with / appended */ 122 | if (stat(name,&s)==0) 123 | { 124 | tm_t = s.st_mtime; 125 | ret = 1; 126 | } 127 | } 128 | filedate = localtime(&tm_t); 129 | 130 | tmzip->tm_sec = filedate->tm_sec; 131 | tmzip->tm_min = filedate->tm_min; 132 | tmzip->tm_hour = filedate->tm_hour; 133 | tmzip->tm_mday = filedate->tm_mday; 134 | tmzip->tm_mon = filedate->tm_mon ; 135 | tmzip->tm_year = filedate->tm_year; 136 | 137 | return ret; 138 | } 139 | #else 140 | uLong filetime(f, tmzip, dt) 141 | char *f; /* name of file to get info on */ 142 | tm_zip *tmzip; /* return value: access, modific. and creation times */ 143 | uLong *dt; /* dostime */ 144 | { 145 | return 0; 146 | } 147 | #endif 148 | #endif 149 | 150 | 151 | 152 | 153 | int check_exist_file(filename) 154 | const char* filename; 155 | { 156 | FILE* ftestexist; 157 | int ret = 1; 158 | ftestexist = FOPEN_FUNC(filename,"rb"); 159 | if (ftestexist==NULL) 160 | ret = 0; 161 | else 162 | fclose(ftestexist); 163 | return ret; 164 | } 165 | 166 | void do_banner() 167 | { 168 | printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n"); 169 | printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n"); 170 | } 171 | 172 | void do_help() 173 | { 174 | printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \ 175 | " -o Overwrite existing file.zip\n" \ 176 | " -a Append to existing file.zip\n" \ 177 | " -0 Store only\n" \ 178 | " -1 Compress faster\n" \ 179 | " -9 Compress better\n\n" \ 180 | " -j exclude path. store only the file name.\n\n"); 181 | } 182 | 183 | /* calculate the CRC32 of a file, 184 | because to encrypt a file, we need known the CRC32 of the file before */ 185 | int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) 186 | { 187 | unsigned long calculate_crc=0; 188 | int err=ZIP_OK; 189 | FILE * fin = FOPEN_FUNC(filenameinzip,"rb"); 190 | 191 | unsigned long size_read = 0; 192 | unsigned long total_read = 0; 193 | if (fin==NULL) 194 | { 195 | err = ZIP_ERRNO; 196 | } 197 | 198 | if (err == ZIP_OK) 199 | do 200 | { 201 | err = ZIP_OK; 202 | size_read = (int)fread(buf,1,size_buf,fin); 203 | if (size_read < size_buf) 204 | if (feof(fin)==0) 205 | { 206 | printf("error in reading %s\n",filenameinzip); 207 | err = ZIP_ERRNO; 208 | } 209 | 210 | if (size_read>0) 211 | calculate_crc = crc32(calculate_crc,buf,size_read); 212 | total_read += size_read; 213 | 214 | } while ((err == ZIP_OK) && (size_read>0)); 215 | 216 | if (fin) 217 | fclose(fin); 218 | 219 | *result_crc=calculate_crc; 220 | printf("file %s crc %lx\n", filenameinzip, calculate_crc); 221 | return err; 222 | } 223 | 224 | int isLargeFile(const char* filename) 225 | { 226 | int largeFile = 0; 227 | ZPOS64_T pos = 0; 228 | FILE* pFile = FOPEN_FUNC(filename, "rb"); 229 | 230 | if(pFile != NULL) 231 | { 232 | int n = FSEEKO_FUNC(pFile, 0, SEEK_END); 233 | pos = FTELLO_FUNC(pFile); 234 | 235 | printf("File : %s is %lld bytes\n", filename, pos); 236 | 237 | if(pos >= 0xffffffff) 238 | largeFile = 1; 239 | 240 | fclose(pFile); 241 | } 242 | 243 | return largeFile; 244 | } 245 | 246 | int main(argc,argv) 247 | int argc; 248 | char *argv[]; 249 | { 250 | int i; 251 | int opt_overwrite=0; 252 | int opt_compress_level=Z_DEFAULT_COMPRESSION; 253 | int opt_exclude_path=0; 254 | int zipfilenamearg = 0; 255 | char filename_try[MAXFILENAME+16]; 256 | int zipok; 257 | int err=0; 258 | int size_buf=0; 259 | void* buf=NULL; 260 | const char* password=NULL; 261 | 262 | 263 | do_banner(); 264 | if (argc==1) 265 | { 266 | do_help(); 267 | return 0; 268 | } 269 | else 270 | { 271 | for (i=1;i='0') && (c<='9')) 285 | opt_compress_level = c-'0'; 286 | if ((c=='j') || (c=='J')) 287 | opt_exclude_path = 1; 288 | 289 | if (((c=='p') || (c=='P')) && (i+1='a') && (rep<='z')) 359 | rep -= 0x20; 360 | } 361 | while ((rep!='Y') && (rep!='N') && (rep!='A')); 362 | if (rep=='N') 363 | zipok = 0; 364 | if (rep=='A') 365 | opt_overwrite = 2; 366 | } 367 | } 368 | 369 | if (zipok==1) 370 | { 371 | zipFile zf; 372 | int errclose; 373 | # ifdef USEWIN32IOAPI 374 | zlib_filefunc64_def ffunc; 375 | fill_win32_filefunc64A(&ffunc); 376 | zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); 377 | # else 378 | zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0); 379 | # endif 380 | 381 | if (zf == NULL) 382 | { 383 | printf("error opening %s\n",filename_try); 384 | err= ZIP_ERRNO; 385 | } 386 | else 387 | printf("creating %s\n",filename_try); 388 | 389 | for (i=zipfilenamearg+1;(i='0') || (argv[i][1]<='9'))) && 396 | (strlen(argv[i]) == 2))) 397 | { 398 | FILE * fin; 399 | int size_read; 400 | const char* filenameinzip = argv[i]; 401 | const char *savefilenameinzip; 402 | zip_fileinfo zi; 403 | unsigned long crcFile=0; 404 | int zip64 = 0; 405 | 406 | zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = 407 | zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; 408 | zi.dosDate = 0; 409 | zi.internal_fa = 0; 410 | zi.external_fa = 0; 411 | filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); 412 | 413 | /* 414 | err = zipOpenNewFileInZip(zf,filenameinzip,&zi, 415 | NULL,0,NULL,0,NULL / * comment * /, 416 | (opt_compress_level != 0) ? Z_DEFLATED : 0, 417 | opt_compress_level); 418 | */ 419 | if ((password != NULL) && (err==ZIP_OK)) 420 | err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); 421 | 422 | zip64 = isLargeFile(filenameinzip); 423 | 424 | /* The path name saved, should not include a leading slash. */ 425 | /*if it did, windows/xp and dynazip couldn't read the zip file. */ 426 | savefilenameinzip = filenameinzip; 427 | while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' ) 428 | { 429 | savefilenameinzip++; 430 | } 431 | 432 | /*should the zip file contain any path at all?*/ 433 | if( opt_exclude_path ) 434 | { 435 | const char *tmpptr; 436 | const char *lastslash = 0; 437 | for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++) 438 | { 439 | if( *tmpptr == '\\' || *tmpptr == '/') 440 | { 441 | lastslash = tmpptr; 442 | } 443 | } 444 | if( lastslash != NULL ) 445 | { 446 | savefilenameinzip = lastslash+1; // base filename follows last slash. 447 | } 448 | } 449 | 450 | /**/ 451 | err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi, 452 | NULL,0,NULL,0,NULL /* comment*/, 453 | (opt_compress_level != 0) ? Z_DEFLATED : 0, 454 | opt_compress_level,0, 455 | /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ 456 | -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 457 | password,crcFile, zip64); 458 | 459 | if (err != ZIP_OK) 460 | printf("error in opening %s in zipfile\n",filenameinzip); 461 | else 462 | { 463 | fin = FOPEN_FUNC(filenameinzip,"rb"); 464 | if (fin==NULL) 465 | { 466 | err=ZIP_ERRNO; 467 | printf("error in opening %s for reading\n",filenameinzip); 468 | } 469 | } 470 | 471 | if (err == ZIP_OK) 472 | do 473 | { 474 | err = ZIP_OK; 475 | size_read = (int)fread(buf,1,size_buf,fin); 476 | if (size_read < size_buf) 477 | if (feof(fin)==0) 478 | { 479 | printf("error in reading %s\n",filenameinzip); 480 | err = ZIP_ERRNO; 481 | } 482 | 483 | if (size_read>0) 484 | { 485 | err = zipWriteInFileInZip (zf,buf,size_read); 486 | if (err<0) 487 | { 488 | printf("error in writing %s in the zipfile\n", 489 | filenameinzip); 490 | } 491 | 492 | } 493 | } while ((err == ZIP_OK) && (size_read>0)); 494 | 495 | if (fin) 496 | fclose(fin); 497 | 498 | if (err<0) 499 | err=ZIP_ERRNO; 500 | else 501 | { 502 | err = zipCloseFileInZip(zf); 503 | if (err!=ZIP_OK) 504 | printf("error in closing %s in the zipfile\n", 505 | filenameinzip); 506 | } 507 | } 508 | } 509 | errclose = zipClose(zf,NULL); 510 | if (errclose != ZIP_OK) 511 | printf("error in closing %s\n",filename_try); 512 | } 513 | else 514 | { 515 | do_help(); 516 | } 517 | 518 | free(buf); 519 | return 0; 520 | } 521 | -------------------------------------------------------------------------------- /nanovg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(nanovg_torus) 4 | 5 | # required for GLU includes 6 | find_package(OpenGL) 7 | 8 | # glew's library is CAPITALIZED.. 9 | find_package(GLEW REQUIRED) 10 | 11 | # glfw3's is NOT 12 | find_package(glfw3 CONFIG REQUIRED) 13 | 14 | add_subdirectory(libs/nanovg) 15 | 16 | include_directories(libs/nanovg/src 17 | ${OPENGL_INCLUDE_DIR} 18 | ${GLEW_INCLUDE_DIRS} 19 | ${glfw3_INCLUDE_DIRS} 20 | ) 21 | 22 | add_executable(nanovg_torus 23 | src/torus.cpp 24 | ) 25 | 26 | target_link_libraries(nanovg_torus 27 | ${GLEW_LIBRARIES} 28 | nanovg 29 | glfw 30 | ${OPENGL_LIBRARIES} 31 | ) 32 | -------------------------------------------------------------------------------- /nanovg/README.md: -------------------------------------------------------------------------------- 1 | # NanoVG 2 | [NanoVG](https://github.com/memononen/nanovg) is a small UI library for OpenGL, with an API modeled after the HTML5 Canvas API. Like [stb](https://github.com/nothings/stb), it's easy to include inside your project instead of importing a package from a repository. 3 | 4 | This source sample is from a [gist](https://gist.github.com/piaoger/66de3489d771c2ec57c7) showing how to render a simple torus and string using NanoVG. A CMakeLists.txt file was added to the nanovg directory to show usage of a `add_subdirectory`. 5 | 6 | Note that NanoVG does not provide fonts directly, expecting the user to pass locations during compile-time. In the interest of having a working example(and not trying to guess font paths), the "NotoSansUI-Regular.ttf" file is included from [Google's Noto fonts collection](https://www.google.com/get/noto/) , licensed under SIL OFL 1.1 7 | 8 | ## Requirements 9 | 10 | Linux: 11 | - libglew-dev 12 | - libglfw3-dev 13 | 14 | OSX: 15 | - glfw 16 | 17 | BSD: 18 | - glew 19 | - glfw 20 | 21 | ## Project Layout 22 | ``` 23 | nanovg 24 | |-- CMakeLists.txt 25 | |-- README.md 26 | |-- include 27 | |-- libs 28 | | `-- nanovg 29 | | |-- CMakeLists.txt 30 | | |-- LICENSE.txt 31 | | |-- README.md 32 | | |-- premake4.lua 33 | | `-- src 34 | | |-- fontstash.h 35 | | |-- nanovg.c 36 | | |-- nanovg.h 37 | | |-- nanovg_gl.h 38 | | |-- nanovg_gl_utils.h 39 | | |-- stb_image.h 40 | | `-- stb_truetype.h 41 | |-- media 42 | | |-- LICENSE 43 | | `-- NotoSansUI-Regular.ttf 44 | `-- src 45 | `-- torus.cpp 46 | ``` 47 | 48 | ## CMakeLists walkthrough 49 | ### CMakeLists.txt 50 | Declare our minimum cmake. There are no real advanced features used, so I usually use 2.8 as an absolute minimum. In 2018+ it's probably safe to use at least 3.0. 51 | ``` 52 | cmake_minimum_required(VERSION 2.8) 53 | ``` 54 | 55 | Declare our project. This should always be the first statement outside of `cmake_minimum_required`, as most variables will not exist until this call. 56 | ``` 57 | project(nanovg_torus) 58 | ``` 59 | OpenGL(specifically GLU) is required, so request it here 60 | ``` 61 | # required for GLU includes 62 | find_package(OpenGL) 63 | ``` 64 | 65 | CMake's case-sensitivity for packages depends on the host OS's filesystem. GLEW is usually provided in ALL-CAPS, so request it here. 66 | ``` 67 | find_package(GLEW REQUIRED) 68 | ``` 69 | 70 | glfw is usually shipped as 'glfw3', so take that into account. Note the use of `CONFIG` in the `find_package` call: this is because CMake ships a `glfw3Config.cmake` file OUTSIDE of our project. 71 | This [StackOverflow answer](https://stackoverflow.com/questions/20746936/cmake-of-what-use-is-find-package-if-you-need-to-specify-cmake-module-path-an) is a good in-depth look at the difference between Module and Config modes in `find_package` 72 | ``` 73 | find_package(glfw3 CONFIG REQUIRED) 74 | ``` 75 | 76 | We have imported all of the packages we need, so it is safe to include the NanoVG subdirectory in `libs`. 77 | One of the easily-overlooked quirks of CMake is that every CMakeLists.txt file creates its own variable space. Much like `fork()` in Unix, the child CMakeLists.txt file will INHERIT variables from the parent, but after that is expected to keep its own. If you expect to use libraries or variables in subdirectories, they must be set BEFORE the `add_subdirectory` call. 78 | 79 | (There are ways around this as demonstrated in the _assimp_ project, but they are not meant to be used on a regular basis) 80 | ``` 81 | add_subdirectory(libs/nanovg) 82 | ``` 83 | 84 | With all of our includes finished, include directories. 85 | ``` 86 | include_directories(libs/nanovg/src 87 | ${OPENGL_INCLUDE_DIR} 88 | ${GLEW_INCLUDE_DIRS} 89 | ${glfw3_INCLUDE_DIRS} 90 | ) 91 | ``` 92 | 93 | Declare our executable, found in `src/torus.cpp` 94 | ``` 95 | add_executable(nanovg_torus 96 | src/torus.cpp 97 | ) 98 | ``` 99 | 100 | Link against our libraries. We have a `nanovg` library variable at this point thanks to the `add_subdirectory` call earlier. 101 | ``` 102 | target_link_libraries(nanovg_torus 103 | ${GLEW_LIBRARIES} 104 | nanovg 105 | glfw 106 | ${OPENGL_LIBRARIES} 107 | ) 108 | ``` 109 | ### libs/nanovg/CMakeLists.txt 110 | Since we are in a subdirectory, we already have a cmake version requirement and a project declared. All that's left is to just declare the library that nanovg builds. 111 | 112 | I like to put `STATUS` messages in subdirectory files, if only because it can help debugging later. There is no requirement to do so. 113 | ``` 114 | message(STATUS "processing nanovg") 115 | ``` 116 | 117 | NanoVG mixes its includes and source, so set the `src/` directory for includes. 118 | ``` 119 | include_directories(src) 120 | ``` 121 | NanoVG is a single source file. By default `add_library` will build a static library, which is fine for a single executable. 122 | ``` 123 | add_library(nanovg 124 | src/nanovg.c 125 | ) 126 | ``` 127 | ## Use 128 | Let's make our build dir and run cmake like usual: 129 | ``` 130 | $ mkdir build 131 | $ cd build 132 | $ cmake .. 133 | ``` 134 | 135 | Then we can make our project. Note that nanovg will be built as a static library before our executable: 136 | ``` 137 | $ make 138 | Scanning dependencies of target nanovg 139 | [ 25%] Building C object libs/nanovg/CMakeFiles/nanovg.dir/src/nanovg.c.o 140 | [ 50%] Linking C static library libnanovg.a 141 | [ 50%] Built target nanovg 142 | Scanning dependencies of target nanovg_torus 143 | [ 75%] Building CXX object CMakeFiles/nanovg_torus.dir/src/torus.cpp.o 144 | [100%] Linking CXX executable nanovg_torus 145 | ``` 146 | 147 | And then we can run our executable: 148 | ``` 149 | $ ./nanovg_torus 150 | ``` 151 | -------------------------------------------------------------------------------- /nanovg/libs/nanovg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | message(STATUS "processing nanovg") 2 | 3 | include_directories(src) 4 | add_library(nanovg 5 | src/nanovg.c 6 | ) 7 | -------------------------------------------------------------------------------- /nanovg/libs/nanovg/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Mikko Mononen memon@inside.org 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. 18 | 19 | -------------------------------------------------------------------------------- /nanovg/libs/nanovg/README.md: -------------------------------------------------------------------------------- 1 | NanoVG 2 | ========== 3 | 4 | NanoVG is small antialiased vector graphics rendering library for OpenGL. It has lean API modeled after HTML5 canvas API. It is aimed to be a practical and fun toolset for building scalable user interfaces and visualizations. 5 | 6 | ## Screenshot 7 | 8 | ![screenshot of some text rendered witht the sample program](/example/screenshot-01.png?raw=true) 9 | 10 | Usage 11 | ===== 12 | 13 | The NanoVG API is modeled loosely on HTML5 canvas API. If you know canvas, you're up to speed with NanoVG in no time. 14 | 15 | ## Creating drawing context 16 | 17 | The drawing context is created using platform specific constructor function. If you're using the OpenGL 2.0 back-end the context is created as follows: 18 | ```C 19 | #define NANOVG_GL2_IMPLEMENTATION // Use GL2 implementation. 20 | #include "nanovg_gl.h" 21 | ... 22 | struct NVGcontext* vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES); 23 | ``` 24 | 25 | The first parameter defines flags for creating the renderer. 26 | 27 | - `NVG_ANTIALIAS` means that the renderer adjusts the geometry to include anti-aliasing. If you're using MSAA, you can omit this flags. 28 | - `NVG_STENCIL_STROKES` means that the render uses better quality rendering for (overlapping) strokes. The quality is mostly visible on wider strokes. If you want speed, you can omit this flag. 29 | 30 | Currently there is an OpenGL back-end for NanoVG: [nanovg_gl.h](/src/nanovg_gl.h) for OpenGL 2.0, OpenGL ES 2.0, OpenGL 3.2 core profile and OpenGL ES 3. The implementation can be chosen using a define as in above example. See the header file and examples for further info. 31 | 32 | *NOTE:* The render target you're rendering to must have stencil buffer. 33 | 34 | ## Drawing shapes with NanoVG 35 | 36 | Drawing a simple shape using NanoVG consists of four steps: 1) begin a new shape, 2) define the path to draw, 3) set fill or stroke, 4) and finally fill or stroke the path. 37 | 38 | ```C 39 | nvgBeginPath(vg); 40 | nvgRect(vg, 100,100, 120,30); 41 | nvgFillColor(vg, nvgRGBA(255,192,0,255)); 42 | nvgFill(vg); 43 | ``` 44 | 45 | Calling `nvgBeginPath()` will clear any existing paths and start drawing from blank slate. There are number of number of functions to define the path to draw, such as rectangle, rounded rectangle and ellipse, or you can use the common moveTo, lineTo, bezierTo and arcTo API to compose the paths step by step. 46 | 47 | ## Understanding Composite Paths 48 | 49 | Because of the way the rendering backend is build in NanoVG, drawing a composite path, that is path consisting from multiple paths defining holes and fills, is a bit more involved. NanoVG uses even-odd filling rule and by default the paths are wound in counter clockwise order. Keep that in mind when drawing using the low level draw API. In order to wind one of the predefined shapes as a hole, you should call `nvgPathWinding(vg, NVG_HOLE)`, or `nvgPathWinding(vg, NVG_CW)` _after_ defining the path. 50 | 51 | ``` C 52 | nvgBeginPath(vg); 53 | nvgRect(vg, 100,100, 120,30); 54 | nvgCircle(vg, 120,120, 5); 55 | nvgPathWinding(vg, NVG_HOLE); // Mark circle as a hole. 56 | nvgFillColor(vg, nvgRGBA(255,192,0,255)); 57 | nvgFill(vg); 58 | ``` 59 | 60 | ## Rendering is wrong, what to do? 61 | 62 | - make sure you have created NanoVG context using one of the `nvgCreatexxx()` calls 63 | - make sure you have initialised OpenGL with *stencil buffer* 64 | - make sure you have cleared stencil buffer 65 | - make sure all rendering calls happen between `nvgBeginFrame()` and `nvgEndFrame()` 66 | - to enable more checks for OpenGL errors, add `NVG_DEBUG` flag to `nvgCreatexxx()` 67 | - if the problem still persists, please report an issue! 68 | 69 | ## OpenGL state touched by the backend 70 | 71 | The OpenGL back-end touches following states: 72 | 73 | When textures are uploaded or updated, the following pixel store is set to defaults: `GL_UNPACK_ALIGNMENT`, `GL_UNPACK_ROW_LENGTH`, `GL_UNPACK_SKIP_PIXELS`, `GL_UNPACK_SKIP_ROWS`. Texture binding is also affected. Texture updates can happen when the user loads images, or when new font glyphs are added. Glyphs are added as needed between calls to `nvgBeginFrame()` and `nvgEndFrame()`. 74 | 75 | The data for the whole frame is buffered and flushed in `nvgEndFrame()`. The following code illustrates the OpenGL state touched by the rendering code: 76 | ```C 77 | glUseProgram(prog); 78 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 79 | glEnable(GL_CULL_FACE); 80 | glCullFace(GL_BACK); 81 | glFrontFace(GL_CCW); 82 | glEnable(GL_BLEND); 83 | glDisable(GL_DEPTH_TEST); 84 | glDisable(GL_SCISSOR_TEST); 85 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 86 | glStencilMask(0xffffffff); 87 | glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 88 | glStencilFunc(GL_ALWAYS, 0, 0xffffffff); 89 | glActiveTexture(GL_TEXTURE0); 90 | glBindBuffer(GL_UNIFORM_BUFFER, buf); 91 | glBindVertexArray(arr); 92 | glBindBuffer(GL_ARRAY_BUFFER, buf); 93 | glBindTexture(GL_TEXTURE_2D, tex); 94 | glUniformBlockBinding(... , GLNVG_FRAG_BINDING); 95 | ``` 96 | 97 | ## API Reference 98 | 99 | See the header file [nanovg.h](/src/nanovg.h) for API reference. 100 | 101 | ## Ports 102 | 103 | - [DX11 port](https://github.com/cmaughan/nanovg) by [Chris Maughan](https://github.com/cmaughan) 104 | - [Metal port](https://github.com/ollix/MetalNanoVG) by [Olli Wang](https://github.com/olliwang) 105 | - [bgfx port](https://github.com/bkaradzic/bgfx/tree/master/examples/20-nanovg) by [Branimir Karadžić](https://github.com/bkaradzic) 106 | 107 | ## Projects using NanoVG 108 | 109 | - [Processing API simulation by vinjn](https://github.com/vinjn/island/blob/master/examples/01-processing/sketch2d.h) 110 | 111 | ## License 112 | The library is licensed under [zlib license](LICENSE.txt) 113 | 114 | ## Discussions 115 | [NanoVG mailing list](https://groups.google.com/forum/#!forum/nanovg) 116 | 117 | ## Links 118 | Uses [stb_truetype](http://nothings.org) (or, optionally, [freetype](http://freetype.org)) for font rendering. 119 | Uses [stb_image](http://nothings.org) for image loading. 120 | -------------------------------------------------------------------------------- /nanovg/libs/nanovg/premake4.lua: -------------------------------------------------------------------------------- 1 | 2 | local action = _ACTION or "" 3 | 4 | solution "nanovg" 5 | location ( "build" ) 6 | configurations { "Debug", "Release" } 7 | platforms {"native", "x64", "x32"} 8 | 9 | project "nanovg" 10 | language "C" 11 | kind "StaticLib" 12 | includedirs { "src" } 13 | files { "src/*.c" } 14 | targetdir("build") 15 | defines { "_CRT_SECURE_NO_WARNINGS" } --,"FONS_USE_FREETYPE" } Uncomment to compile with FreeType support 16 | 17 | configuration "Debug" 18 | defines { "DEBUG" } 19 | flags { "Symbols", "ExtraWarnings"} 20 | 21 | configuration "Release" 22 | defines { "NDEBUG" } 23 | flags { "Optimize", "ExtraWarnings"} 24 | 25 | project "example_gl2" 26 | 27 | kind "ConsoleApp" 28 | language "C" 29 | files { "example/example_gl2.c", "example/demo.c", "example/perf.c" } 30 | includedirs { "src", "example" } 31 | targetdir("build") 32 | links { "nanovg" } 33 | 34 | configuration { "linux" } 35 | linkoptions { "`pkg-config --libs glfw3`" } 36 | links { "GL", "GLU", "m", "GLEW" } 37 | defines { "NANOVG_GLEW" } 38 | 39 | configuration { "windows" } 40 | links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" } 41 | defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" } 42 | 43 | configuration { "macosx" } 44 | links { "glfw3" } 45 | linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" } 46 | 47 | configuration "Debug" 48 | defines { "DEBUG" } 49 | flags { "Symbols", "ExtraWarnings"} 50 | 51 | configuration "Release" 52 | defines { "NDEBUG" } 53 | flags { "Optimize", "ExtraWarnings"} 54 | 55 | project "example_gl3" 56 | kind "ConsoleApp" 57 | language "C" 58 | files { "example/example_gl3.c", "example/demo.c", "example/perf.c" } 59 | includedirs { "src", "example" } 60 | targetdir("build") 61 | links { "nanovg" } 62 | 63 | configuration { "linux" } 64 | linkoptions { "`pkg-config --libs glfw3`" } 65 | links { "GL", "GLU", "m", "GLEW" } 66 | defines { "NANOVG_GLEW" } 67 | 68 | configuration { "windows" } 69 | links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" } 70 | defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" } 71 | 72 | configuration { "macosx" } 73 | links { "glfw3" } 74 | linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" } 75 | 76 | configuration "Debug" 77 | defines { "DEBUG" } 78 | flags { "Symbols", "ExtraWarnings"} 79 | 80 | configuration "Release" 81 | defines { "NDEBUG" } 82 | flags { "Optimize", "ExtraWarnings"} 83 | 84 | project "example_gl2_msaa" 85 | kind "ConsoleApp" 86 | language "C" 87 | defines { "DEMO_MSAA" } 88 | files { "example/example_gl2.c", "example/demo.c", "example/perf.c" } 89 | includedirs { "src", "example" } 90 | targetdir("build") 91 | links { "nanovg" } 92 | 93 | configuration { "linux" } 94 | linkoptions { "`pkg-config --libs glfw3`" } 95 | links { "GL", "GLU", "m", "GLEW" } 96 | defines { "NANOVG_GLEW" } 97 | 98 | configuration { "windows" } 99 | links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" } 100 | defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" } 101 | 102 | configuration { "macosx" } 103 | links { "glfw3" } 104 | linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" } 105 | 106 | configuration "Debug" 107 | defines { "DEBUG" } 108 | flags { "Symbols", "ExtraWarnings"} 109 | 110 | configuration "Release" 111 | defines { "NDEBUG" } 112 | flags { "Optimize", "ExtraWarnings"} 113 | 114 | project "example_gl3_msaa" 115 | kind "ConsoleApp" 116 | language "C" 117 | defines { "DEMO_MSAA" } 118 | files { "example/example_gl3.c", "example/demo.c", "example/perf.c" } 119 | includedirs { "src", "example" } 120 | targetdir("build") 121 | links { "nanovg" } 122 | 123 | configuration { "linux" } 124 | linkoptions { "`pkg-config --libs glfw3`" } 125 | links { "GL", "GLU", "m", "GLEW" } 126 | defines { "NANOVG_GLEW" } 127 | 128 | configuration { "windows" } 129 | links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" } 130 | defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" } 131 | 132 | configuration { "macosx" } 133 | links { "glfw3" } 134 | linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" } 135 | 136 | configuration "Debug" 137 | defines { "DEBUG" } 138 | flags { "Symbols", "ExtraWarnings"} 139 | 140 | configuration "Release" 141 | defines { "NDEBUG" } 142 | flags { "Optimize", "ExtraWarnings"} 143 | 144 | project "example_fbo" 145 | kind "ConsoleApp" 146 | language "C" 147 | files { "example/example_fbo.c", "example/perf.c" } 148 | includedirs { "src", "example" } 149 | targetdir("build") 150 | links { "nanovg" } 151 | 152 | configuration { "linux" } 153 | linkoptions { "`pkg-config --libs glfw3`" } 154 | links { "GL", "GLU", "m", "GLEW" } 155 | 156 | configuration { "windows" } 157 | links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" } 158 | defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" } 159 | 160 | configuration { "macosx" } 161 | links { "glfw3" } 162 | linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" } 163 | 164 | configuration "Debug" 165 | defines { "DEBUG" } 166 | flags { "Symbols", "ExtraWarnings"} 167 | 168 | configuration "Release" 169 | defines { "NDEBUG" } 170 | flags { "Optimize", "ExtraWarnings"} 171 | 172 | project "example_gles2" 173 | kind "ConsoleApp" 174 | language "C" 175 | files { "example/example_gles2.c", "example/demo.c", "example/perf.c" } 176 | includedirs { "src", "example" } 177 | targetdir("build") 178 | links { "nanovg" } 179 | 180 | configuration { "linux" } 181 | linkoptions { "`pkg-config --libs glfw3`" } 182 | links { "GL", "GLU", "m", "GLEW" } 183 | 184 | configuration { "windows" } 185 | links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" } 186 | defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" } 187 | 188 | configuration { "macosx" } 189 | links { "glfw3" } 190 | linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" } 191 | 192 | configuration "Debug" 193 | defines { "DEBUG" } 194 | flags { "Symbols", "ExtraWarnings"} 195 | 196 | configuration "Release" 197 | defines { "NDEBUG" } 198 | flags { "Optimize", "ExtraWarnings"} 199 | 200 | project "example_gles3" 201 | kind "ConsoleApp" 202 | language "C" 203 | files { "example/example_gles3.c", "example/demo.c", "example/perf.c" } 204 | includedirs { "src", "example" } 205 | targetdir("build") 206 | links { "nanovg" } 207 | 208 | configuration { "linux" } 209 | linkoptions { "`pkg-config --libs glfw3`" } 210 | links { "GL", "GLU", "m", "GLEW" } 211 | 212 | configuration { "windows" } 213 | links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" } 214 | defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" } 215 | 216 | configuration { "macosx" } 217 | links { "glfw3" } 218 | linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" } 219 | 220 | configuration "Debug" 221 | defines { "DEBUG" } 222 | flags { "Symbols", "ExtraWarnings"} 223 | 224 | configuration "Release" 225 | defines { "NDEBUG" } 226 | flags { "Optimize", "ExtraWarnings"} 227 | -------------------------------------------------------------------------------- /nanovg/libs/nanovg/src/nanovg_gl_utils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2009-2013 Mikko Mononen memon@inside.org 3 | // 4 | // This software is provided 'as-is', without any express or implied 5 | // warranty. In no event will the authors be held liable for any damages 6 | // arising from the use of this software. 7 | // Permission is granted to anyone to use this software for any purpose, 8 | // including commercial applications, and to alter it and redistribute it 9 | // freely, subject to the following restrictions: 10 | // 1. The origin of this software must not be misrepresented; you must not 11 | // claim that you wrote the original software. If you use this software 12 | // in a product, an acknowledgment in the product documentation would be 13 | // appreciated but is not required. 14 | // 2. Altered source versions must be plainly marked as such, and must not be 15 | // misrepresented as being the original software. 16 | // 3. This notice may not be removed or altered from any source distribution. 17 | // 18 | #ifndef NANOVG_GL_UTILS_H 19 | #define NANOVG_GL_UTILS_H 20 | 21 | struct NVGLUframebuffer { 22 | NVGcontext* ctx; 23 | GLuint fbo; 24 | GLuint rbo; 25 | GLuint texture; 26 | int image; 27 | }; 28 | typedef struct NVGLUframebuffer NVGLUframebuffer; 29 | 30 | // Helper function to create GL frame buffer to render to. 31 | void nvgluBindFramebuffer(NVGLUframebuffer* fb); 32 | NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags); 33 | void nvgluDeleteFramebuffer(NVGLUframebuffer* fb); 34 | 35 | #endif // NANOVG_GL_UTILS_H 36 | 37 | #ifdef NANOVG_GL_IMPLEMENTATION 38 | 39 | #if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3) 40 | // FBO is core in OpenGL 3>. 41 | # define NANOVG_FBO_VALID 1 42 | #elif defined(NANOVG_GL2) 43 | // On OS X including glext defines FBO on GL2 too. 44 | # ifdef __APPLE__ 45 | # include 46 | # define NANOVG_FBO_VALID 1 47 | # endif 48 | #endif 49 | 50 | static GLint defaultFBO = -1; 51 | 52 | NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags) 53 | { 54 | #ifdef NANOVG_FBO_VALID 55 | GLint defaultFBO; 56 | GLint defaultRBO; 57 | NVGLUframebuffer* fb = NULL; 58 | 59 | glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); 60 | glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO); 61 | 62 | fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer)); 63 | if (fb == NULL) goto error; 64 | memset(fb, 0, sizeof(NVGLUframebuffer)); 65 | 66 | fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL); 67 | 68 | #if defined NANOVG_GL2 69 | fb->texture = nvglImageHandleGL2(ctx, fb->image); 70 | #elif defined NANOVG_GL3 71 | fb->texture = nvglImageHandleGL3(ctx, fb->image); 72 | #elif defined NANOVG_GLES2 73 | fb->texture = nvglImageHandleGLES2(ctx, fb->image); 74 | #elif defined NANOVG_GLES3 75 | fb->texture = nvglImageHandleGLES3(ctx, fb->image); 76 | #endif 77 | 78 | fb->ctx = ctx; 79 | 80 | // frame buffer object 81 | glGenFramebuffers(1, &fb->fbo); 82 | glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo); 83 | 84 | // render buffer object 85 | glGenRenderbuffers(1, &fb->rbo); 86 | glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo); 87 | glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h); 88 | 89 | // combine all 90 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); 91 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); 92 | 93 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 94 | #ifdef GL_DEPTH24_STENCIL8 95 | // If GL_STENCIL_INDEX8 is not supported, try GL_DEPTH24_STENCIL8 as a fallback. 96 | // Some graphics cards require a depth buffer along with a stencil. 97 | glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h); 98 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); 99 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); 100 | 101 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 102 | #endif // GL_DEPTH24_STENCIL8 103 | goto error; 104 | } 105 | 106 | glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); 107 | glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); 108 | return fb; 109 | error: 110 | glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); 111 | glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); 112 | nvgluDeleteFramebuffer(fb); 113 | return NULL; 114 | #else 115 | NVG_NOTUSED(ctx); 116 | NVG_NOTUSED(w); 117 | NVG_NOTUSED(h); 118 | NVG_NOTUSED(imageFlags); 119 | return NULL; 120 | #endif 121 | } 122 | 123 | void nvgluBindFramebuffer(NVGLUframebuffer* fb) 124 | { 125 | #ifdef NANOVG_FBO_VALID 126 | if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); 127 | glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : defaultFBO); 128 | #else 129 | NVG_NOTUSED(fb); 130 | #endif 131 | } 132 | 133 | void nvgluDeleteFramebuffer(NVGLUframebuffer* fb) 134 | { 135 | #ifdef NANOVG_FBO_VALID 136 | if (fb == NULL) return; 137 | if (fb->fbo != 0) 138 | glDeleteFramebuffers(1, &fb->fbo); 139 | if (fb->rbo != 0) 140 | glDeleteRenderbuffers(1, &fb->rbo); 141 | if (fb->image >= 0) 142 | nvgDeleteImage(fb->ctx, fb->image); 143 | fb->ctx = NULL; 144 | fb->fbo = 0; 145 | fb->rbo = 0; 146 | fb->texture = 0; 147 | fb->image = -1; 148 | free(fb); 149 | #else 150 | NVG_NOTUSED(fb); 151 | #endif 152 | } 153 | 154 | #endif // NANOVG_GL_IMPLEMENTATION 155 | -------------------------------------------------------------------------------- /nanovg/media/LICENSE: -------------------------------------------------------------------------------- 1 | This Font Software is licensed under the SIL Open Font License, 2 | Version 1.1. 3 | 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | ----------------------------------------------------------- 8 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 9 | ----------------------------------------------------------- 10 | 11 | PREAMBLE 12 | The goals of the Open Font License (OFL) are to stimulate worldwide 13 | development of collaborative font projects, to support the font 14 | creation efforts of academic and linguistic communities, and to 15 | provide a free and open framework in which fonts may be shared and 16 | improved in partnership with others. 17 | 18 | The OFL allows the licensed fonts to be used, studied, modified and 19 | redistributed freely as long as they are not sold by themselves. The 20 | fonts, including any derivative works, can be bundled, embedded, 21 | redistributed and/or sold with any software provided that any reserved 22 | names are not used by derivative works. The fonts and derivatives, 23 | however, cannot be released under any other type of license. The 24 | requirement for fonts to remain under this license does not apply to 25 | any document created using the fonts or their derivatives. 26 | 27 | DEFINITIONS 28 | "Font Software" refers to the set of files released by the Copyright 29 | Holder(s) under this license and clearly marked as such. This may 30 | include source files, build scripts and documentation. 31 | 32 | "Reserved Font Name" refers to any names specified as such after the 33 | copyright statement(s). 34 | 35 | "Original Version" refers to the collection of Font Software 36 | components as distributed by the Copyright Holder(s). 37 | 38 | "Modified Version" refers to any derivative made by adding to, 39 | deleting, or substituting -- in part or in whole -- any of the 40 | components of the Original Version, by changing formats or by porting 41 | the Font Software to a new environment. 42 | 43 | "Author" refers to any designer, engineer, programmer, technical 44 | writer or other person who contributed to the Font Software. 45 | 46 | PERMISSION & CONDITIONS 47 | Permission is hereby granted, free of charge, to any person obtaining 48 | a copy of the Font Software, to use, study, copy, merge, embed, 49 | modify, redistribute, and sell modified and unmodified copies of the 50 | Font Software, subject to the following conditions: 51 | 52 | 1) Neither the Font Software nor any of its individual components, in 53 | Original or Modified Versions, may be sold by itself. 54 | 55 | 2) Original or Modified Versions of the Font Software may be bundled, 56 | redistributed and/or sold with any software, provided that each copy 57 | contains the above copyright notice and this license. These can be 58 | included either as stand-alone text files, human-readable headers or 59 | in the appropriate machine-readable metadata fields within text or 60 | binary files as long as those fields can be easily viewed by the user. 61 | 62 | 3) No Modified Version of the Font Software may use the Reserved Font 63 | Name(s) unless explicit written permission is granted by the 64 | corresponding Copyright Holder. This restriction only applies to the 65 | primary font name as presented to the users. 66 | 67 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 68 | Software shall not be used to promote, endorse or advertise any 69 | Modified Version, except to acknowledge the contribution(s) of the 70 | Copyright Holder(s) and the Author(s) or with their explicit written 71 | permission. 72 | 73 | 5) The Font Software, modified or unmodified, in part or in whole, 74 | must be distributed entirely under this license, and must not be 75 | distributed under any other license. The requirement for fonts to 76 | remain under this license does not apply to any document created using 77 | the Font Software. 78 | 79 | TERMINATION 80 | This license becomes null and void if any of the above conditions are 81 | not met. 82 | 83 | DISCLAIMER 84 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 85 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 86 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 87 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 88 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 89 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 90 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 91 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 92 | OTHER DEALINGS IN THE FONT SOFTWARE. 93 | -------------------------------------------------------------------------------- /nanovg/media/NotoSansUI-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mechazoidal/cmake_cookbook/96840862823a4d902460d460eb6829f1121c7294/nanovg/media/NotoSansUI-Regular.ttf -------------------------------------------------------------------------------- /nanovg/src/torus.cpp: -------------------------------------------------------------------------------- 1 | // Taken directly from: https://gist.github.com/piaoger/66de3489d771c2ec57c7 2 | // with a slight modification to line 127 for font directory. 3 | 4 | // An OpenGL3 Exmaple: glew, glfw and nanovg. 5 | // 2D and 3D in same scene. Torus is drawn with static display list. 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "GL/glew.h" 12 | 13 | #define GLFW_INCLUDE_GLU 14 | #include "GLFW/glfw3.h" 15 | 16 | #include "nanovg.h" 17 | #define NANOVG_GL2_IMPLEMENTATION 18 | #include "nanovg_gl.h" 19 | 20 | 21 | // Event Handlers 22 | 23 | struct Mouse { 24 | float x; 25 | float y; 26 | }; 27 | 28 | struct Mouse mouse = {0,0}; 29 | bool isTracking = false; 30 | 31 | static void OnKeyDown(GLFWwindow* window, int key, int scancode, int action, int mods) 32 | { 33 | } 34 | 35 | static void OnMouseMove(GLFWwindow* window, double x, double y) 36 | { 37 | mouse.x = x; 38 | mouse.y = y; 39 | } 40 | 41 | static void OnMouseDown(GLFWwindow* window, int button, int action, int mods) 42 | { 43 | if (action == GLFW_PRESS) { 44 | isTracking = !isTracking; 45 | } 46 | } 47 | 48 | static void OnResize(GLFWwindow * window, int w, int h){ 49 | glfwSetWindowSize(window, w,h); 50 | } 51 | 52 | 53 | // Draw 54 | 55 | static void drawTorus(int numMajor, int numMinor, float majorRadius, float minorRadius) 56 | { 57 | static double PI = 3.1415926535897932384626433832795; 58 | 59 | double majorStep = 2.0 * PI / numMajor; 60 | double minorStep = 2.0 * PI / numMinor; 61 | 62 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 63 | 64 | for (int i = 0; i < numMajor; ++i) { 65 | 66 | double a0 = i * majorStep; 67 | double a1 = a0 + majorStep; 68 | GLdouble x0 = cos(a0); 69 | GLdouble y0 = sin(a0); 70 | GLdouble x1 = cos(a1); 71 | GLdouble y1 = sin(a1); 72 | 73 | glBegin(GL_TRIANGLE_STRIP); 74 | 75 | for (int j = 0; j <= numMinor; ++j) { 76 | double b = j * minorStep; 77 | GLdouble c = cos(b); 78 | GLdouble r = minorRadius * c + majorRadius; 79 | GLdouble z = minorRadius * sin(b); 80 | 81 | glNormal3d(x0 * c, y0 * c, z / minorRadius); 82 | glTexCoord2d(i / (GLdouble) numMajor, j / (GLdouble) numMinor); 83 | glVertex3d(x0 * r, y0 * r, z); 84 | 85 | glNormal3d(x1 * c, y1 * c, z / minorRadius); 86 | glTexCoord2d((i + 1) / (GLdouble) numMajor, j / (GLdouble) numMinor); 87 | glVertex3d(x1 * r, y1 * r, z); 88 | } 89 | 90 | glEnd(); 91 | } 92 | } 93 | 94 | 95 | int main(){ 96 | 97 | GLFWwindow * window; 98 | NVGcontext *vg; 99 | 100 | int width = 800; 101 | int height = 600; 102 | 103 | if (!glfwInit()) { 104 | printf("Could not initialize glfw.\n"); 105 | return -1; 106 | } 107 | 108 | // Initialize window 109 | window = glfwCreateWindow(width, height, "solidmcp", NULL, NULL); 110 | if (!window) { 111 | glfwTerminate(); 112 | return -1; 113 | } 114 | glfwMakeContextCurrent(window); 115 | 116 | if(glewInit() != GLEW_OK) { 117 | printf("Could not initialize glew.\n"); 118 | return -1; 119 | } 120 | glGetError(); 121 | 122 | vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG); 123 | if (vg == NULL) { 124 | printf("Could not initialize nanovg.\n"); 125 | return -1; 126 | } 127 | int font = nvgCreateFont(vg, "font", "../media/NotoSansUI-Regular.ttf"); 128 | if (font < 0) { 129 | printf("nvgCreateFont() failed\n"); 130 | return -1; 131 | } 132 | 133 | //callbacks 134 | glfwSetKeyCallback(window, OnKeyDown); 135 | glfwSetWindowSizeCallback(window, OnResize); 136 | glfwSetCursorPosCallback(window, OnMouseMove ); 137 | glfwSetMouseButtonCallback(window, OnMouseDown ); 138 | 139 | glfwSwapInterval(1); 140 | 141 | while( !glfwWindowShouldClose(window)){ 142 | 143 | // set viewport 144 | glfwGetFramebufferSize(window, &width, &height); 145 | 146 | float ratio = (float) width / height; 147 | glViewport(0,0,width,height); 148 | 149 | glClearColor(0.3f, 0.3f, 0.32f, 1.0f); 150 | glClear(GL_COLOR_BUFFER_BIT); 151 | 152 | glMatrixMode( GL_PROJECTION ); 153 | glLoadIdentity(); 154 | gluPerspective(60, ratio, .1, 100); 155 | glMatrixMode( GL_MODELVIEW ); 156 | glLoadIdentity(); 157 | gluLookAt(0,0,5, 0, 0, -1, 0, 1, 0); 158 | 159 | if(isTracking) { 160 | glRotatef(mouse.x, 0, 1, 0); 161 | glRotatef(mouse.y, 1, 0, 0); 162 | } 163 | 164 | // Draw Stuff 165 | drawTorus(20, 10, 1, 0.5); 166 | 167 | nvgBeginFrame(vg, width, height, ratio); 168 | // Reset polygon mode 169 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 170 | 171 | nvgFontSize(vg, 100); 172 | nvgFontFace(vg, "font"); 173 | nvgFillColor(vg, nvgRGBA(0, 0, 255, 255)); 174 | nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); 175 | nvgText(vg, 10, 10, "OpenGL2 Exmaple", NULL); 176 | 177 | nvgEndFrame(vg); 178 | 179 | glfwSwapBuffers(window); 180 | glfwPollEvents(); 181 | } 182 | 183 | nvgDeleteGL2(vg); 184 | glfwTerminate(); 185 | glfwDestroyWindow(window); 186 | return 0; 187 | } 188 | -------------------------------------------------------------------------------- /zmq/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(zmq_example) 4 | 5 | # Add our project-specific Modules directory to the cmake module search path 6 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") 7 | 8 | # With our project module set, find the library in the system. 9 | find_package(ZeroMQ) 10 | 11 | # An example of echoing a variable set by find_package 12 | message(STATUS "ZeroMQ version: ${ZeroMQ_VERSION}") 13 | 14 | # include_directories applies to ALL following targets once set. 15 | include_directories(include 16 | ${ZeroMQ_INCLUDE_DIR} 17 | ) 18 | 19 | # Declare our executable targets and their sources 20 | add_executable(wuclient 21 | src/wuclient.c 22 | ) 23 | 24 | add_executable(wuserver 25 | src/wuserver.c 26 | ) 27 | 28 | add_executable(version 29 | src/version.c 30 | ) 31 | 32 | # Link our executables. 33 | # Note that libraries may be linked to a target immediately after declaring it 34 | # with add_executable, but I prefer to keep them in one section. 35 | target_link_libraries(wuclient 36 | ${ZeroMQ_LIBRARIES} 37 | ) 38 | 39 | target_link_libraries(wuserver 40 | ${ZeroMQ_LIBRARIES} 41 | ) 42 | 43 | target_link_libraries(version 44 | ${ZeroMQ_LIBRARIES} 45 | ) 46 | -------------------------------------------------------------------------------- /zmq/README.md: -------------------------------------------------------------------------------- 1 | # ZeroMQ 2 | ZeroMQ(or ØMQ in UTF-8) is a high-performance async messaging library with an interface resembling Berkeley sockets. Though the core is in C++, the project leads prefer to keep the library interface in C and as simple as possible. 3 | 4 | Up until version 4.2(per [this issue](https://github.com/zeromq/cppzmq/issues/127)), ZMQ did not ship a FindZeroMQ.cmake file. Since some packaging systems are still at 4.1, we include the official FindZeroMQ.cmake file, in cmake/Modules. 5 | 6 | 7 | ## Requirements: 8 | ### Linux: 9 | - libczmq-dev 10 | 11 | ### BSD: 12 | - zeromq 13 | 14 | ### OSX: 15 | - zmq 16 | 17 | ## Project Layout 18 | ``` 19 | zmq 20 | |-- CMakeLists.txt 21 | |-- README.md 22 | |-- cmake 23 | | `-- Modules 24 | | |-- FindZeroMQ-LICENSE.txt 25 | | |-- FindZeroMQ.cmake 26 | | `-- README.txt 27 | |-- include 28 | | |-- config.h 29 | | `-- zhelpers.h 30 | `-- src 31 | |-- config.c 32 | |-- version.c 33 | |-- wuclient.c 34 | `-- wuserver.c 35 | ``` 36 | 37 | ## CMakeLists walkthrough 38 | ### CMakeLists.txt 39 | Declare our minimum cmake. There are no real advanced features used, so I usually use 2.8 as an absolute minimum. In 2018+ it's probably safe to use at least 3.0. 40 | ``` 41 | cmake_minimum_required(VERSION 2.8) 42 | ``` 43 | 44 | Declare our project. This should always be the first statement outside of `cmake_minimum_required`, as most variables will not exist until this call. 45 | ``` 46 | project(zmq_example) 47 | ``` 48 | 49 | Add our project-specific Modules directory to the cmake module search path 50 | ``` 51 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") 52 | ``` 53 | 54 | With our project module set, find the library in the system. 55 | ``` 56 | find_package(ZeroMQ) 57 | ``` 58 | 59 | An example of echoing a variable set by `find_package`: CMake will already echo the version it finds, but try moving this before the `find_package` call and see what is printed. 60 | ``` 61 | message(STATUS "ZeroMQ version: ${ZeroMQ_VERSION}") 62 | ``` 63 | 64 | `include_directories` applies to ALL following targets once set. 65 | ``` 66 | include_directories(include 67 | ${ZeroMQ_INCLUDE_DIR} 68 | ) 69 | ``` 70 | 71 | Declare our executable targets and their sources 72 | ``` 73 | add_executable(wuclient 74 | src/wuclient.c 75 | ) 76 | add_executable(wuserver 77 | src/wuserver.c 78 | ) 79 | add_executable(version 80 | src/version.c 81 | ) 82 | ``` 83 | 84 | Link our executables. 85 | Note that libraries may be linked to a target immediately after declaring it 86 | with `add_executable`, but I prefer to keep them in one section. 87 | ``` 88 | target_link_libraries(wuclient 89 | ${ZeroMQ_LIBRARIES} 90 | ) 91 | 92 | target_link_libraries(wuserver 93 | ${ZeroMQ_LIBRARIES} 94 | ) 95 | 96 | target_link_libraries(version 97 | ${ZeroMQ_LIBRARIES} 98 | ) 99 | ``` 100 | 101 | ## Use 102 | Let's make our build dir and run cmake like usual: 103 | ``` 104 | $ mkdir build 105 | $ cd build 106 | $ cmake .. 107 | ``` 108 | 109 | Then we can make our project. 110 | ``` 111 | $ make 112 | Scanning dependencies of target version 113 | [ 16%] Building C object CMakeFiles/version.dir/src/version.c.o 114 | [ 33%] Linking C executable version 115 | [ 33%] Built target version 116 | Scanning dependencies of target wuserver 117 | [ 50%] Building C object CMakeFiles/wuserver.dir/src/wuserver.c.o 118 | [ 66%] Linking C executable wuserver 119 | CMakeFiles/wuserver.dir/src/wuserver.c.o: In function `main': 120 | [ 66%] Built target wuserver 121 | Scanning dependencies of target wuclient 122 | [ 83%] Building C object CMakeFiles/wuclient.dir/src/wuclient.c.o 123 | [100%] Linking C executable wuclient 124 | [100%] Built target wuclient 125 | ``` 126 | And then we have our three target executables: `version`, `wuclient`, and `wuserver` 127 | -------------------------------------------------------------------------------- /zmq/cmake/Modules/FindZeroMQ-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Remus License Version 1.0 2 | ======================================================================== 3 | Copyright (c) 2012 Kitware Inc. 28 Corporate Drive 4 | Clifton Park, NY, 12065, USA. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of Kitware nor the names of any contributors may 17 | be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 24 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | -------------------------------------------------------------------------------- /zmq/cmake/Modules/FindZeroMQ.cmake: -------------------------------------------------------------------------------- 1 | ##============================================================================= 2 | ## 3 | ## Copyright (c) Kitware, Inc. 4 | ## All rights reserved. 5 | ## See LICENSE.txt for details. 6 | ## 7 | ## This software is distributed WITHOUT ANY WARRANTY; without even 8 | ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 9 | ## PURPOSE. See the above copyright notice for more information. 10 | ## 11 | ##============================================================================= 12 | # - Try to find ZeroMQ headers and libraries 13 | # 14 | # Usage of this module as follows: 15 | # 16 | # find_package(ZeroMQ) 17 | # 18 | # Variables used by this module, they can change the default behaviour and need 19 | # to be set before calling find_package: 20 | # 21 | # ZeroMQ_ROOT_DIR Set this variable to the root installation of 22 | # ZeroMQ if the module has problems finding 23 | # the proper installation path. 24 | # 25 | # Variables defined by this module: 26 | # 27 | # ZeroMQ_FOUND System has ZeroMQ libs/headers 28 | # ZeroMQ_LIBRARIES The ZeroMQ libraries 29 | # ZeroMQ_INCLUDE_DIR The location of ZeroMQ headers 30 | # ZeroMQ_VERSION The version of ZeroMQ 31 | 32 | find_path(ZeroMQ_ROOT_DIR 33 | NAMES include/zmq.h 34 | ) 35 | 36 | if(MSVC) 37 | #add in all the names it can have on windows 38 | if(CMAKE_GENERATOR_TOOLSET MATCHES "v140" OR MSVC14) 39 | set(_zmq_TOOLSET "-v140") 40 | elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v120" OR MSVC12) 41 | set(_zmq_TOOLSET "-v120") 42 | elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v110_xp") 43 | set(_zmq_TOOLSET "-v110_xp") 44 | elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v110" OR MSVC11) 45 | set(_zmq_TOOLSET "-v110") 46 | elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v100" OR MSVC10) 47 | set(_zmq_TOOLSET "-v100") 48 | elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v90" OR MSVC90) 49 | set(_zmq_TOOLSET "-v90") 50 | endif() 51 | 52 | set(_zmq_versions 53 | "4_1_5" "4_1_4" "4_1_3" "4_1_2" "4_1_1" "4_1_0" 54 | "4_0_8" "4_0_7" "4_0_6" "4_0_5" "4_0_4" "4_0_3" "4_0_2" "4_0_1" "4_0_0" 55 | "3_2_5" "3_2_4" "3_2_3" "3_2_2" "3_2_1" "3_2_0" "3_1_0") 56 | 57 | set(_zmq_release_names) 58 | set(_zmq_debug_names) 59 | foreach( ver ${_zmq_versions}) 60 | list(APPEND _zmq_release_names "libzmq${_zmq_TOOLSET}-mt-${ver}") 61 | endforeach() 62 | foreach( ver ${_zmq_versions}) 63 | list(APPEND _zmq_debug_names "libzmq${_zmq_TOOLSET}-mt-gd-${ver}") 64 | endforeach() 65 | 66 | #now try to find the release and debug version 67 | find_library(ZeroMQ_LIBRARY_RELEASE 68 | NAMES ${_zmq_release_names} zmq libzmq 69 | HINTS ${ZeroMQ_ROOT_DIR}/bin 70 | ${ZeroMQ_ROOT_DIR}/lib 71 | ) 72 | 73 | find_library(ZeroMQ_LIBRARY_DEBUG 74 | NAMES ${_zmq_debug_names} zmq libzmq 75 | HINTS ${ZeroMQ_ROOT_DIR}/bin 76 | ${ZeroMQ_ROOT_DIR}/lib 77 | ) 78 | 79 | if(ZeroMQ_LIBRARY_RELEASE AND ZeroMQ_LIBRARY_DEBUG) 80 | set(ZeroMQ_LIBRARY 81 | debug ${ZeroMQ_LIBRARY_DEBUG} 82 | optimized ${ZeroMQ_LIBRARY_RELEASE} 83 | ) 84 | elseif(ZeroMQ_LIBRARY_RELEASE) 85 | set(ZeroMQ_LIBRARY ${ZeroMQ_LIBRARY_RELEASE}) 86 | elseif(ZeroMQ_LIBRARY_DEBUG) 87 | set(ZeroMQ_LIBRARY ${ZeroMQ_LIBRARY_DEBUG}) 88 | endif() 89 | 90 | else() 91 | find_library(ZeroMQ_LIBRARY 92 | NAMES zmq libzmq 93 | HINTS ${ZeroMQ_ROOT_DIR}/lib 94 | ) 95 | endif() 96 | 97 | find_path(ZeroMQ_INCLUDE_DIR 98 | NAMES zmq.h 99 | HINTS ${ZeroMQ_ROOT_DIR}/include 100 | ) 101 | 102 | function(extract_version_value value_name file_name value) 103 | file(STRINGS ${file_name} val REGEX "${value_name} .") 104 | string(FIND ${val} " " last REVERSE) 105 | string(SUBSTRING ${val} ${last} -1 val) 106 | string(STRIP ${val} val) 107 | set(${value} ${val} PARENT_SCOPE) 108 | endfunction(extract_version_value) 109 | 110 | extract_version_value("ZMQ_VERSION_MAJOR" ${ZeroMQ_INCLUDE_DIR}/zmq.h MAJOR) 111 | extract_version_value("ZMQ_VERSION_MINOR" ${ZeroMQ_INCLUDE_DIR}/zmq.h MINOR) 112 | extract_version_value("ZMQ_VERSION_PATCH" ${ZeroMQ_INCLUDE_DIR}/zmq.h PATCH) 113 | 114 | set(ZeroMQ_VER "${MAJOR}.${MINOR}.${PATCH}") 115 | 116 | #We are using the 2.8.10 signature of find_package_handle_standard_args, 117 | #as that is the version that ParaView 5.1 && VTK 6/7 ship, and inject 118 | #into the CMake module path. This allows our FindModule to work with 119 | #projects that include VTK/ParaView before searching for Remus 120 | include(FindPackageHandleStandardArgs) 121 | find_package_handle_standard_args( 122 | ZeroMQ 123 | REQUIRED_VARS ZeroMQ_LIBRARY ZeroMQ_INCLUDE_DIR 124 | VERSION_VAR ZeroMQ_VER 125 | ) 126 | 127 | set(ZeroMQ_FOUND ${ZEROMQ_FOUND}) 128 | set(ZeroMQ_INCLUDE_DIRS ${ZeroMQ_INCLUDE_DIR}) 129 | set(ZeroMQ_LIBRARIES ${ZeroMQ_LIBRARY}) 130 | set(ZeroMQ_VERSION ${ZeroMQ_VER}) 131 | 132 | mark_as_advanced( 133 | ZeroMQ_ROOT_DIR 134 | ZeroMQ_LIBRARY 135 | ZeroMQ_LIBRARY_DEBUG 136 | ZeroMQ_LIBRARY_RELEASE 137 | ZeroMQ_INCLUDE_DIR 138 | ZeroMQ_VERSION 139 | ) 140 | -------------------------------------------------------------------------------- /zmq/cmake/Modules/README.txt: -------------------------------------------------------------------------------- 1 | These were taken from https://github.com/carpe-noctem-cassel/symrock/tree/zmq/capnzero/cmake 2 | -------------------------------------------------------------------------------- /zmq/include/config.h: -------------------------------------------------------------------------------- 1 | // Taken from https://lists.zeromq.org/pipermail/zeromq-dev/2018-January/032232.html 2 | // This ensures that sockets time out much faster than system defaults. 3 | #ifndef __CONFIG_H_INCLUDED__ 4 | #define __CONFIG_H_INCLUDED__ 5 | 6 | #define ZMQ_TCP_KEEPALIVE 1 7 | #define ZMQ_TCP_KEEPALIVE_IDLE 30 8 | #define ZMQ_TCP_KEEPALIVE_INTVL 5 9 | #define ZMQ_TCP_KEEPALIVE_CNT 6 10 | 11 | #endif // __CONFIG_H_INCLUDED__ 12 | -------------------------------------------------------------------------------- /zmq/include/zhelpers.h: -------------------------------------------------------------------------------- 1 | /* ===================================================================== 2 | zhelpers.h 3 | 4 | Helper header file for example applications. 5 | ===================================================================== 6 | */ 7 | 8 | #ifndef __ZHELPERS_H_INCLUDED__ 9 | #define __ZHELPERS_H_INCLUDED__ 10 | 11 | // Include a bunch of headers that we will need in the examples 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #if (!defined (WIN32)) 24 | # include 25 | #endif 26 | 27 | #if (defined (WIN32)) 28 | # include 29 | #endif 30 | 31 | // Version checking, and patch up missing constants to match 2.1 32 | #if ZMQ_VERSION_MAJOR == 2 33 | # error "Please upgrade to ZeroMQ/3.2 for these examples" 34 | #endif 35 | 36 | // On some version of Windows, POSIX subsystem is not installed by default. 37 | // So define srandom and random ourself. 38 | #if (defined (WIN32)) 39 | # define srandom srand 40 | # define random rand 41 | #endif 42 | 43 | // Provide random number from 0..(num-1) 44 | #define randof(num) (int) ((float) (num) * random () / (RAND_MAX + 1.0)) 45 | 46 | // Receive 0MQ string from socket and convert into C string 47 | // Caller must free returned string. Returns NULL if the context 48 | // is being terminated. 49 | static char * 50 | s_recv (void *socket) { 51 | char buffer [256]; 52 | int size = zmq_recv (socket, buffer, 255, 0); 53 | if (size == -1) 54 | return NULL; 55 | buffer[size] = '\0'; 56 | 57 | #if (defined (WIN32)) 58 | return strdup (buffer); 59 | #else 60 | return strndup (buffer, sizeof(buffer) - 1); 61 | #endif 62 | 63 | // remember that the strdup family of functions use malloc/alloc for space for the new string. It must be manually 64 | // freed when you are done with it. Failure to do so will allow a heap attack. 65 | } 66 | 67 | // Convert C string to 0MQ string and send to socket 68 | static int 69 | s_send (void *socket, char *string) { 70 | int size = zmq_send (socket, string, strlen (string), 0); 71 | return size; 72 | } 73 | 74 | // Sends string as 0MQ string, as multipart non-terminal 75 | static int 76 | s_sendmore (void *socket, char *string) { 77 | int size = zmq_send (socket, string, strlen (string), ZMQ_SNDMORE); 78 | return size; 79 | } 80 | 81 | // Receives all message parts from socket, prints neatly 82 | // 83 | static void 84 | s_dump (void *socket) 85 | { 86 | int rc; 87 | 88 | zmq_msg_t message; 89 | rc = zmq_msg_init (&message); 90 | assert (rc == 0); 91 | 92 | puts ("----------------------------------------"); 93 | // Process all parts of the message 94 | do { 95 | int size = zmq_msg_recv (&message, socket, 0); 96 | assert (size >= 0); 97 | 98 | // Dump the message as text or binary 99 | char *data = (char*)zmq_msg_data (&message); 100 | assert (data != 0); 101 | int is_text = 1; 102 | int char_nbr; 103 | for (char_nbr = 0; char_nbr < size; char_nbr++) { 104 | if ((unsigned char) data [char_nbr] < 32 105 | || (unsigned char) data [char_nbr] > 126) { 106 | is_text = 0; 107 | } 108 | } 109 | 110 | printf ("[%03d] ", size); 111 | for (char_nbr = 0; char_nbr < size; char_nbr++) { 112 | if (is_text) { 113 | printf ("%c", data [char_nbr]); 114 | } else { 115 | printf ("%02X", (unsigned char) data [char_nbr]); 116 | } 117 | } 118 | printf ("\n"); 119 | } while (zmq_msg_more (&message)); 120 | 121 | rc = zmq_msg_close (&message); 122 | assert (rc == 0); 123 | } 124 | 125 | #if (!defined (WIN32)) 126 | // Set simple random printable identity on socket 127 | // Caution: 128 | // DO NOT call this version of s_set_id from multiple threads on MS Windows 129 | // since s_set_id will call rand() on MS Windows. rand(), however, is not 130 | // reentrant or thread-safe. See issue #521. 131 | static void 132 | s_set_id (void *socket) 133 | { 134 | char identity [10]; 135 | sprintf (identity, "%04X-%04X", randof (0x10000), randof (0x10000)); 136 | zmq_setsockopt (socket, ZMQ_IDENTITY, identity, strlen (identity)); 137 | } 138 | #else 139 | // Fix #521 for MS Windows. 140 | static void 141 | s_set_id(void *socket, intptr_t id) 142 | { 143 | char identity [10]; 144 | sprintf(identity, "%04X", (int)id); 145 | zmq_setsockopt(socket, ZMQ_IDENTITY, identity, strlen(identity)); 146 | } 147 | #endif 148 | 149 | // Sleep for a number of milliseconds 150 | static void 151 | s_sleep (int msecs) 152 | { 153 | #if (defined (WIN32)) 154 | Sleep (msecs); 155 | #else 156 | struct timespec t; 157 | t.tv_sec = msecs / 1000; 158 | t.tv_nsec = (msecs % 1000) * 1000000; 159 | nanosleep (&t, NULL); 160 | #endif 161 | } 162 | 163 | // Return current system clock as milliseconds 164 | static int64_t 165 | s_clock (void) 166 | { 167 | #if (defined (WIN32)) 168 | SYSTEMTIME st; 169 | GetSystemTime (&st); 170 | return (int64_t) st.wSecond * 1000 + st.wMilliseconds; 171 | #else 172 | struct timeval tv; 173 | gettimeofday (&tv, NULL); 174 | return (int64_t) (tv.tv_sec * 1000 + tv.tv_usec / 1000); 175 | #endif 176 | } 177 | 178 | // Print formatted string to stdout, prefixed by date/time and 179 | // terminated with a newline. 180 | 181 | static void 182 | s_console (const char *format, ...) 183 | { 184 | time_t curtime = time (NULL); 185 | struct tm *loctime = localtime (&curtime); 186 | char *formatted = (char*)malloc (20); 187 | strftime (formatted, 20, "%y-%m-%d %H:%M:%S ", loctime); 188 | printf ("%s", formatted); 189 | free (formatted); 190 | 191 | va_list argptr; 192 | va_start (argptr, format); 193 | vprintf (format, argptr); 194 | va_end (argptr); 195 | printf ("\n"); 196 | } 197 | 198 | #endif // __ZHELPERS_H_INCLUDED__ 199 | -------------------------------------------------------------------------------- /zmq/src/config.c: -------------------------------------------------------------------------------- 1 | zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE, 2 | -------------------------------------------------------------------------------- /zmq/src/version.c: -------------------------------------------------------------------------------- 1 | // version.c from http://zguide.zeromq.org/page:all 2 | // Report 0MQ version 3 | 4 | #include 5 | 6 | int main (void) 7 | { 8 | int major, minor, patch; 9 | zmq_version (&major, &minor, &patch); 10 | printf ("Current 0MQ version is %d.%d.%d\n", major, minor, patch); 11 | return 0; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /zmq/src/wuclient.c: -------------------------------------------------------------------------------- 1 | // wuclient.c from http://zguide.zeromq.org/page:all 2 | 3 | // Weather update client 4 | // Connects SUB socket to tcp://localhost:5556 5 | // Collects weather updates and finds avg temp in zipcode 6 | 7 | #include "zhelpers.h" 8 | 9 | int main (int argc, char *argv []) 10 | { 11 | // Socket to talk to server 12 | printf ("Collecting updates from weather server…\n"); 13 | void *context = zmq_ctx_new (); 14 | void *subscriber = zmq_socket (context, ZMQ_SUB); 15 | int rc = zmq_connect (subscriber, "tcp://localhost:5556"); 16 | assert (rc == 0); 17 | 18 | // Subscribe to zipcode, default is NYC, 10001 19 | char *filter = (argc > 1)? argv [1]: "10001 "; 20 | rc = zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE, 21 | filter, strlen (filter)); 22 | assert (rc == 0); 23 | 24 | // Process 100 updates 25 | int update_nbr; 26 | long total_temp = 0; 27 | for (update_nbr = 0; update_nbr < 100; update_nbr++) { 28 | char *string = s_recv (subscriber); 29 | 30 | int zipcode, temperature, relhumidity; 31 | sscanf (string, "%d %d %d", 32 | &zipcode, &temperature, &relhumidity); 33 | total_temp += temperature; 34 | free (string); 35 | } 36 | printf ("Average temperature for zipcode '%s' was %dF\n", 37 | filter, (int) (total_temp / update_nbr)); 38 | 39 | zmq_close (subscriber); 40 | zmq_ctx_destroy (context); 41 | return 0; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /zmq/src/wuserver.c: -------------------------------------------------------------------------------- 1 | // wuclient.c from http://zguide.zeromq.org/page:all 2 | 3 | // Weather update server 4 | // Binds PUB socket to tcp://*:5556 5 | // Publishes random weather updates 6 | #include "zhelpers.h" 7 | 8 | int main (void) 9 | { 10 | // Prepare our context and publisher 11 | void *context = zmq_ctx_new (); 12 | void *publisher = zmq_socket (context, ZMQ_PUB); 13 | int rc = zmq_bind (publisher, "tcp://*:5556"); 14 | assert (rc == 0); 15 | 16 | // Initialize random number generator 17 | srandom ((unsigned) time (NULL)); 18 | while (1) { 19 | // Get values that will fool the boss 20 | int zipcode, temperature, relhumidity; 21 | zipcode = randof (100000); 22 | temperature = randof (215) - 80; 23 | relhumidity = randof (50) + 10; 24 | 25 | // Send message to all subscribers 26 | char update [20]; 27 | sprintf (update, "%05d %d %d", zipcode, temperature, relhumidity); 28 | s_send (publisher, update); 29 | } 30 | zmq_close (publisher); 31 | zmq_ctx_destroy (context); 32 | return 0; 33 | } 34 | 35 | --------------------------------------------------------------------------------