Working on conan integration.
This should automatically add support for imgui etc.
This commit is contained in:
		
							parent
							
								
									49f0a2f6b8
								
							
						
					
					
						commit
						47543a5a9b
					
				|  | @ -3,23 +3,18 @@ project(kge) | |||
| 
 | ||||
| set(CMAKE_CXX_STANDARD 14) | ||||
| 
 | ||||
| add_library(imgui | ||||
| 	imgui/imconfig.h | ||||
| 	imgui/imgui.cpp | ||||
| 	imgui/imgui.h | ||||
| 	imgui/imgui_draw.cpp | ||||
| 	imgui/imgui_impl_opengl3.h | ||||
| 	imgui/imgui_impl_opengl3.cpp | ||||
| 	imgui/imgui_impl_opengl3_loader.h | ||||
| 	imgui/imgui_impl_sdl3.cpp | ||||
| 	imgui/imgui_impl_sdl3.h | ||||
| 	imgui/imgui_internal.h | ||||
| 	imgui/imgui_tables.cpp | ||||
| 	imgui/imgui_widgets.cpp | ||||
| 	imgui/imstb_rectpack.h | ||||
| 	imgui/imstb_textedit.h | ||||
| 	imgui/imstb_truetype.h | ||||
| ) | ||||
| find_package(imgui REQUIRED) | ||||
| find_package(glfw3 REQUIRED) | ||||
| find_package(glew REQUIRED) | ||||
| 
 | ||||
| add_executable(kge kge.cc Cursor.h Buffer.h Platform.cc Platform.h | ||||
| 	imgui.h) | ||||
| add_executable(kge kge.cc | ||||
| #	Buffer.cc | ||||
| #	Cursor.cc | ||||
| 	GUI.cc | ||||
| 	Platform.cc | ||||
| ) | ||||
| target_link_libraries(kge | ||||
| 	imgui::imgui | ||||
| 	GLEW::GLEW | ||||
| 	glfw | ||||
| ) | ||||
|  |  | |||
|  | @ -0,0 +1,17 @@ | |||
| //
 | ||||
| // Created by kyle on 2023-10-04.
 | ||||
| //
 | ||||
| 
 | ||||
| 
 | ||||
| #include "GUI.h" | ||||
| 
 | ||||
| 
 | ||||
| static struct { | ||||
| 	ImGuiIO	*io; | ||||
| } gui; | ||||
| 
 | ||||
| void | ||||
| InitGUI() | ||||
| { | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,15 @@ | |||
| //
 | ||||
| // Created by kyle on 2023-10-04.
 | ||||
| //
 | ||||
| 
 | ||||
| #ifndef KGE_GUI_H | ||||
| #define KGE_GUI_H | ||||
| 
 | ||||
| #include "imgui.h" | ||||
| #include <GL/glew.h> | ||||
| #include <GLFW/glfw3.h> | ||||
| 
 | ||||
| void	InitGUI(); | ||||
| 
 | ||||
| 
 | ||||
| #endif //KGE_GUI_H
 | ||||
|  | @ -7,6 +7,7 @@ | |||
| 
 | ||||
| 
 | ||||
| #ifdef WIN32 | ||||
| #include "imgui/imgui.h" | ||||
| #include <windows.h> | ||||
| 
 | ||||
| extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); | ||||
|  |  | |||
|  | @ -0,0 +1,548 @@ | |||
| # This file is managed by Conan, contents will be overwritten. | ||||
| # To keep your changes, remove these comment lines, but the plugin won't be able to modify your requirements | ||||
| 
 | ||||
| set(CONAN_MINIMUM_VERSION 2.0.5) | ||||
| 
 | ||||
| 
 | ||||
| function(detect_os OS OS_API_LEVEL OS_SDK OS_SUBSYSTEM OS_VERSION) | ||||
|     # it could be cross compilation | ||||
|     message(STATUS "CMake-Conan: cmake_system_name=${CMAKE_SYSTEM_NAME}") | ||||
|     if(CMAKE_SYSTEM_NAME AND NOT CMAKE_SYSTEM_NAME STREQUAL "Generic") | ||||
|         if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") | ||||
|             set(${OS} Macos PARENT_SCOPE) | ||||
|         elseif(${CMAKE_SYSTEM_NAME} STREQUAL "QNX") | ||||
|             set(${OS} Neutrino PARENT_SCOPE) | ||||
|         elseif(${CMAKE_SYSTEM_NAME} STREQUAL "CYGWIN") | ||||
|             set(${OS} Windows PARENT_SCOPE) | ||||
|             set(${OS_SUBSYSTEM} cygwin PARENT_SCOPE) | ||||
|         elseif(${CMAKE_SYSTEM_NAME} MATCHES "^MSYS") | ||||
|             set(${OS} Windows PARENT_SCOPE) | ||||
|             set(${OS_SUBSYSTEM} msys2 PARENT_SCOPE) | ||||
|         else() | ||||
|             set(${OS} ${CMAKE_SYSTEM_NAME} PARENT_SCOPE) | ||||
|         endif() | ||||
|         if(${CMAKE_SYSTEM_NAME} STREQUAL "Android") | ||||
|             string(REGEX MATCH "[0-9]+" _OS_API_LEVEL ${ANDROID_PLATFORM}) | ||||
|             message(STATUS "CMake-Conan: android_platform=${ANDROID_PLATFORM}") | ||||
|             set(${OS_API_LEVEL} ${_OS_API_LEVEL} PARENT_SCOPE) | ||||
|         endif() | ||||
|         if(CMAKE_SYSTEM_NAME MATCHES "Darwin|iOS|tvOS|watchOS") | ||||
|             # CMAKE_OSX_SYSROOT contains the full path to the SDK for MakeFile/Ninja | ||||
|             # generators, but just has the original input string for Xcode. | ||||
|             if(NOT IS_DIRECTORY ${CMAKE_OSX_SYSROOT}) | ||||
|                 set(_OS_SDK ${CMAKE_OSX_SYSROOT}) | ||||
|             else() | ||||
|                 if(CMAKE_OSX_SYSROOT MATCHES Simulator) | ||||
|                     set(apple_platform_suffix simulator) | ||||
|                 else() | ||||
|                     set(apple_platform_suffix os) | ||||
|                 endif() | ||||
|                 if(CMAKE_OSX_SYSROOT MATCHES AppleTV) | ||||
|                     set(_OS_SDK "appletv${apple_platform_suffix}") | ||||
|                 elseif(CMAKE_OSX_SYSROOT MATCHES iPhone) | ||||
|                     set(_OS_SDK "iphone${apple_platform_suffix}") | ||||
|                 elseif(CMAKE_OSX_SYSROOT MATCHES Watch) | ||||
|                     set(_OS_SDK "watch${apple_platform_suffix}") | ||||
|                 endif() | ||||
|             endif() | ||||
|             if(DEFINED _OS_SDK) | ||||
|                 message(STATUS "CMake-Conan: cmake_osx_sysroot=${CMAKE_OSX_SYSROOT}") | ||||
|                 set(${OS_SDK} ${_OS_SDK} PARENT_SCOPE) | ||||
|             endif() | ||||
|             if(DEFINED CMAKE_OSX_DEPLOYMENT_TARGET) | ||||
|                 message(STATUS "CMake-Conan: cmake_osx_deployment_target=${CMAKE_OSX_DEPLOYMENT_TARGET}") | ||||
|                 set(${OS_VERSION} ${CMAKE_OSX_DEPLOYMENT_TARGET} PARENT_SCOPE) | ||||
|             endif() | ||||
|         endif() | ||||
|     endif() | ||||
| endfunction() | ||||
| 
 | ||||
| 
 | ||||
| function(detect_arch ARCH) | ||||
|     # CMAKE_OSX_ARCHITECTURES can contain multiple architectures, but Conan only supports one. | ||||
|     # Therefore this code only finds one. If the recipes support multiple architectures, the | ||||
|     # build will work. Otherwise, there will be a linker error for the missing architecture(s). | ||||
|     if(DEFINED CMAKE_OSX_ARCHITECTURES) | ||||
|         string(REPLACE " " ";" apple_arch_list "${CMAKE_OSX_ARCHITECTURES}") | ||||
|         list(LENGTH apple_arch_list apple_arch_count) | ||||
|         if(apple_arch_count GREATER 1) | ||||
|             message(WARNING "CMake-Conan: Multiple architectures detected, this will only work if Conan recipe(s) produce fat binaries.") | ||||
|         endif() | ||||
|     endif() | ||||
|     if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64|arm64" OR CMAKE_OSX_ARCHITECTURES MATCHES arm64) | ||||
|         set(_ARCH armv8) | ||||
|     elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "armv7-a|armv7l" OR CMAKE_OSX_ARCHITECTURES MATCHES armv7) | ||||
|         set(_ARCH armv7) | ||||
|     elseif(CMAKE_OSX_ARCHITECTURES MATCHES armv7s) | ||||
|         set(_ARCH armv7s) | ||||
|     elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686" OR CMAKE_OSX_ARCHITECTURES MATCHES i386) | ||||
|         set(_ARCH x86) | ||||
|     elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64|amd64|x86_64" OR CMAKE_OSX_ARCHITECTURES MATCHES x86_64) | ||||
|         set(_ARCH x86_64) | ||||
|     endif() | ||||
|     message(STATUS "CMake-Conan: cmake_system_processor=${_ARCH}") | ||||
|     set(${ARCH} ${_ARCH} PARENT_SCOPE) | ||||
| endfunction() | ||||
| 
 | ||||
| 
 | ||||
| function(detect_cxx_standard CXX_STANDARD) | ||||
|     set(${CXX_STANDARD} ${CMAKE_CXX_STANDARD} PARENT_SCOPE) | ||||
|     if(CMAKE_CXX_EXTENSIONS) | ||||
|         set(${CXX_STANDARD} "gnu${CMAKE_CXX_STANDARD}" PARENT_SCOPE) | ||||
|     endif() | ||||
| endfunction() | ||||
| 
 | ||||
| macro(detect_gnu_libstdcxx) | ||||
|     # _CONAN_IS_GNU_LIBSTDCXX true if GNU libstdc++ | ||||
|     check_cxx_source_compiles(" | ||||
|     #include <cstddef> | ||||
|     #if !defined(__GLIBCXX__) && !defined(__GLIBCPP__) | ||||
|     static_assert(false); | ||||
|     #endif | ||||
|     int main(){}" _CONAN_IS_GNU_LIBSTDCXX) | ||||
| 
 | ||||
|     # _CONAN_GNU_LIBSTDCXX_IS_CXX11_ABI true if C++11 ABI | ||||
|     check_cxx_source_compiles(" | ||||
|     #include <string> | ||||
|     static_assert(sizeof(std::string) != sizeof(void*), \"using libstdc++\"); | ||||
|     int main () {}" _CONAN_GNU_LIBSTDCXX_IS_CXX11_ABI) | ||||
| 
 | ||||
|     set(_CONAN_GNU_LIBSTDCXX_SUFFIX "") | ||||
|     if(_CONAN_GNU_LIBSTDCXX_IS_CXX11_ABI) | ||||
|         set(_CONAN_GNU_LIBSTDCXX_SUFFIX "11") | ||||
|     endif() | ||||
|     unset (_CONAN_GNU_LIBSTDCXX_IS_CXX11_ABI) | ||||
| endmacro() | ||||
| 
 | ||||
| macro(detect_libcxx) | ||||
|     # _CONAN_IS_LIBCXX true if LLVM libc++ | ||||
|     check_cxx_source_compiles(" | ||||
|     #include <cstddef> | ||||
|     #if !defined(_LIBCPP_VERSION) | ||||
|        static_assert(false); | ||||
|     #endif | ||||
|     int main(){}" _CONAN_IS_LIBCXX) | ||||
| endmacro() | ||||
| 
 | ||||
| 
 | ||||
| function(detect_lib_cxx OS LIB_CXX) | ||||
|     if(${OS} STREQUAL "Android") | ||||
|         message(STATUS "CMake-Conan: android_stl=${ANDROID_STL}") | ||||
|         set(${LIB_CXX} ${ANDROID_STL} PARENT_SCOPE) | ||||
|         return() | ||||
|     endif() | ||||
| 
 | ||||
|     include(CheckCXXSourceCompiles) | ||||
| 
 | ||||
|     if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") | ||||
|         detect_gnu_libstdcxx() | ||||
|         set(${LIB_CXX} "libstdc++${_CONAN_GNU_LIBSTDCXX_SUFFIX}" PARENT_SCOPE) | ||||
|     elseif(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang") | ||||
|         set(${LIB_CXX} "libc++" PARENT_SCOPE) | ||||
|     elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_SYSTEM_NAME MATCHES "Windows") | ||||
|         # Check for libc++ | ||||
|         detect_libcxx() | ||||
|         if(_CONAN_IS_LIBCXX) | ||||
|             set(${LIB_CXX} "libc++" PARENT_SCOPE) | ||||
|             return() | ||||
|         endif() | ||||
| 
 | ||||
|         # Check for libstdc++ | ||||
|         detect_gnu_libstdcxx() | ||||
|         if(_CONAN_IS_GNU_LIBSTDCXX) | ||||
|             set(${LIB_CXX} "libstdc++${_CONAN_GNU_LIBSTDCXX_SUFFIX}" PARENT_SCOPE) | ||||
|             return() | ||||
|         endif() | ||||
| 
 | ||||
|         # TODO: it would be an error if we reach this point | ||||
|     elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") | ||||
|         # Do nothing - compiler.runtime and compiler.runtime_type | ||||
|         # should be handled separately: https://github.com/conan-io/cmake-conan/pull/516 | ||||
|         return() | ||||
|     else() | ||||
|         # TODO: unable to determine, ask user to provide a full profile file instead | ||||
|     endif() | ||||
| endfunction() | ||||
| 
 | ||||
| 
 | ||||
| function(detect_compiler COMPILER COMPILER_VERSION COMPILER_RUNTIME COMPILER_RUNTIME_TYPE) | ||||
|     if(DEFINED CMAKE_CXX_COMPILER_ID) | ||||
|         set(_COMPILER ${CMAKE_CXX_COMPILER_ID}) | ||||
|         set(_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION}) | ||||
|     else() | ||||
|         if(NOT DEFINED CMAKE_C_COMPILER_ID) | ||||
|             message(FATAL_ERROR "C or C++ compiler not defined") | ||||
|         endif() | ||||
|         set(_COMPILER ${CMAKE_C_COMPILER_ID}) | ||||
|         set(_COMPILER_VERSION ${CMAKE_C_COMPILER_VERSION}) | ||||
|     endif() | ||||
| 
 | ||||
|     message(STATUS "CMake-Conan: CMake compiler=${_COMPILER}") | ||||
|     message(STATUS "CMake-Conan: CMake compiler version=${_COMPILER_VERSION}") | ||||
| 
 | ||||
|     if(_COMPILER MATCHES MSVC) | ||||
|         set(_COMPILER "msvc") | ||||
|         string(SUBSTRING ${MSVC_VERSION} 0 3 _COMPILER_VERSION) | ||||
|         # Configure compiler.runtime and compiler.runtime_type settings for MSVC | ||||
|         if(CMAKE_MSVC_RUNTIME_LIBRARY) | ||||
|             set(_KNOWN_MSVC_RUNTIME_VALUES "") | ||||
|             list(APPEND _KNOWN_MSVC_RUNTIME_VALUES MultiThreaded MultiThreadedDLL) | ||||
|             list(APPEND _KNOWN_MSVC_RUNTIME_VALUES MultiThreadedDebug MultiThreadedDebugDLL) | ||||
|             list(APPEND _KNOWN_MSVC_RUNTIME_VALUES MultiThreaded$<$<CONFIG:Debug>:Debug> MultiThreaded$<$<CONFIG:Debug>:Debug>DLL) | ||||
| 
 | ||||
|             # only accept the 6 possible values, otherwise we don't don't know to map this | ||||
|             if(NOT CMAKE_MSVC_RUNTIME_LIBRARY IN_LIST _KNOWN_MSVC_RUNTIME_VALUES) | ||||
|                 message(FATAL_ERROR "CMake-Conan: unable to map MSVC runtime: ${CMAKE_MSVC_RUNTIME_LIBRARY} to Conan settings") | ||||
|             endif() | ||||
|              | ||||
|             # Runtime is "dynamic" in all cases if it ends in DLL | ||||
|             if(CMAKE_MSVC_RUNTIME_LIBRARY MATCHES ".*DLL$") | ||||
|                 set(_COMPILER_RUNTIME "dynamic") | ||||
|             else() | ||||
|                 set(_COMPILER_RUNTIME "static") | ||||
|             endif() | ||||
| 
 | ||||
|             # Only define compiler.runtime_type when explicitly requested | ||||
|             # If a generator expression is used, let Conan handle it conditional on build_type | ||||
|             get_property(_IS_MULTI_CONFIG_GENERATOR GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) | ||||
|             if(NOT CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "<CONFIG:Debug>:Debug>") | ||||
|                 if(CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "Debug") | ||||
|                     set(_COMPILER_RUNTIME_TYPE "Debug") | ||||
|                 else() | ||||
|                     set(_COMPILER_RUNTIME_TYPE "Release") | ||||
|                 endif() | ||||
|             endif() | ||||
| 
 | ||||
|             unset(_KNOWN_MSVC_RUNTIME_VALUES) | ||||
|             unset(_IS_MULTI_CONFIG_GENERATOR) | ||||
|         endif() | ||||
|     elseif(_COMPILER MATCHES AppleClang) | ||||
|         set(_COMPILER "apple-clang") | ||||
|         string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION}) | ||||
|         list(GET VERSION_LIST 0 _COMPILER_VERSION) | ||||
|     elseif(_COMPILER MATCHES Clang) | ||||
|         set(_COMPILER "clang") | ||||
|         string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION}) | ||||
|         list(GET VERSION_LIST 0 _COMPILER_VERSION) | ||||
|     elseif(_COMPILER MATCHES GNU) | ||||
|         set(_COMPILER "gcc") | ||||
|         string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION}) | ||||
|         list(GET VERSION_LIST 0 _COMPILER_VERSION) | ||||
|     endif() | ||||
| 
 | ||||
|     message(STATUS "CMake-Conan: [settings] compiler=${_COMPILER}") | ||||
|     message(STATUS "CMake-Conan: [settings] compiler.version=${_COMPILER_VERSION}") | ||||
|     if (_COMPILER_RUNTIME) | ||||
|         message(STATUS "CMake-Conan: [settings] compiler.runtime=${_COMPILER_RUNTIME}") | ||||
|     endif() | ||||
|     if (_COMPILER_RUNTIME_TYPE) | ||||
|         message(STATUS "CMake-Conan: [settings] compiler.runtime_type=${_COMPILER_RUNTIME_TYPE}") | ||||
|     endif() | ||||
| 
 | ||||
|     set(${COMPILER} ${_COMPILER} PARENT_SCOPE) | ||||
|     set(${COMPILER_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE) | ||||
|     set(${COMPILER_RUNTIME} ${_COMPILER_RUNTIME} PARENT_SCOPE) | ||||
|     set(${COMPILER_RUNTIME_TYPE} ${_COMPILER_RUNTIME_TYPE} PARENT_SCOPE) | ||||
| endfunction() | ||||
| 
 | ||||
| function(detect_build_type BUILD_TYPE) | ||||
|     get_property(_MULTICONFIG_GENERATOR GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) | ||||
|     if(NOT _MULTICONFIG_GENERATOR) | ||||
|         # Only set when we know we are in a single-configuration generator | ||||
|         # Note: we may want to fail early if `CMAKE_BUILD_TYPE` is not defined | ||||
|         set(${BUILD_TYPE} ${CMAKE_BUILD_TYPE} PARENT_SCOPE) | ||||
|     endif() | ||||
| endfunction() | ||||
| 
 | ||||
| macro(append_compiler_executables_configuration) | ||||
|     set(_conan_c_compiler "") | ||||
|     set(_conan_cpp_compiler "") | ||||
|     if(CMAKE_C_COMPILER) | ||||
|         set(_conan_c_compiler "\"c\":\"${CMAKE_C_COMPILER}\",") | ||||
|     else() | ||||
|         message(WARNING "CMake-Conan: The C compiler is not defined. " | ||||
|                         "Please define CMAKE_C_COMPILER or enable the C language.") | ||||
|     endif() | ||||
|     if(CMAKE_CXX_COMPILER) | ||||
|         set(_conan_cpp_compiler "\"cpp\":\"${CMAKE_CXX_COMPILER}\"") | ||||
|     else() | ||||
|         message(WARNING "CMake-Conan: The C++ compiler is not defined. " | ||||
|                         "Please define CMAKE_CXX_COMPILER or enable the C++ language.") | ||||
|     endif() | ||||
| 
 | ||||
|     string(APPEND PROFILE "tools.build:compiler_executables={${_conan_c_compiler}${_conan_cpp_compiler}}\n") | ||||
|     unset(_conan_c_compiler) | ||||
|     unset(_conan_cpp_compiler) | ||||
| endmacro() | ||||
| 
 | ||||
| 
 | ||||
| function(detect_host_profile output_file) | ||||
|     detect_os(MYOS MYOS_API_LEVEL MYOS_SDK MYOS_SUBSYSTEM MYOS_VERSION) | ||||
|     detect_arch(MYARCH) | ||||
|     detect_compiler(MYCOMPILER MYCOMPILER_VERSION MYCOMPILER_RUNTIME MYCOMPILER_RUNTIME_TYPE) | ||||
|     detect_cxx_standard(MYCXX_STANDARD) | ||||
|     detect_lib_cxx(MYOS MYLIB_CXX) | ||||
|     detect_build_type(MYBUILD_TYPE) | ||||
| 
 | ||||
|     set(PROFILE "") | ||||
|     string(APPEND PROFILE "[settings]\n") | ||||
|     if(MYARCH) | ||||
|         string(APPEND PROFILE arch=${MYARCH} "\n") | ||||
|     endif() | ||||
|     if(MYOS) | ||||
|         string(APPEND PROFILE os=${MYOS} "\n") | ||||
|     endif() | ||||
|     if(MYOS_API_LEVEL) | ||||
|         string(APPEND PROFILE os.api_level=${MYOS_API_LEVEL} "\n") | ||||
|     endif() | ||||
|     if(MYOS_VERSION) | ||||
|         string(APPEND PROFILE os.version=${MYOS_VERSION} "\n") | ||||
|     endif() | ||||
|     if(MYOS_SDK) | ||||
|         string(APPEND PROFILE os.sdk=${MYOS_SDK} "\n") | ||||
|     endif() | ||||
|     if(MYOS_SUBSYSTEM) | ||||
|         string(APPEND PROFILE os.subsystem=${MYOS_SUBSYSTEM} "\n") | ||||
|     endif() | ||||
|     if(MYCOMPILER) | ||||
|         string(APPEND PROFILE compiler=${MYCOMPILER} "\n") | ||||
|     endif() | ||||
|     if(MYCOMPILER_VERSION) | ||||
|         string(APPEND PROFILE compiler.version=${MYCOMPILER_VERSION} "\n") | ||||
|     endif() | ||||
|     if(MYCOMPILER_RUNTIME) | ||||
|         string(APPEND PROFILE compiler.runtime=${MYCOMPILER_RUNTIME} "\n") | ||||
|     endif() | ||||
|     if(MYCOMPILER_RUNTIME_TYPE) | ||||
|         string(APPEND PROFILE compiler.runtime_type=${MYCOMPILER_RUNTIME_TYPE} "\n") | ||||
|     endif() | ||||
|     if(MYCXX_STANDARD) | ||||
|         string(APPEND PROFILE compiler.cppstd=${MYCXX_STANDARD} "\n") | ||||
|     endif() | ||||
|     if(MYLIB_CXX) | ||||
|         string(APPEND PROFILE compiler.libcxx=${MYLIB_CXX} "\n") | ||||
|     endif() | ||||
|     if(MYBUILD_TYPE) | ||||
|         string(APPEND PROFILE "build_type=${MYBUILD_TYPE}\n") | ||||
|     endif() | ||||
| 
 | ||||
|     if(NOT DEFINED output_file) | ||||
|         set(_FN "${CMAKE_BINARY_DIR}/profile") | ||||
|     else() | ||||
|         set(_FN ${output_file}) | ||||
|     endif() | ||||
| 
 | ||||
|     string(APPEND PROFILE "[conf]\n") | ||||
|     string(APPEND PROFILE "tools.cmake.cmaketoolchain:generator=${CMAKE_GENERATOR}\n") | ||||
| 
 | ||||
|     # propagate compilers via profile | ||||
|     append_compiler_executables_configuration() | ||||
| 
 | ||||
|     if(${MYOS} STREQUAL "Android") | ||||
|         string(APPEND PROFILE "tools.android:ndk_path=${CMAKE_ANDROID_NDK}\n") | ||||
|     endif() | ||||
| 
 | ||||
|     message(STATUS "CMake-Conan: Creating profile ${_FN}") | ||||
|     file(WRITE ${_FN} ${PROFILE}) | ||||
|     message(STATUS "CMake-Conan: Profile: \n${PROFILE}") | ||||
| endfunction() | ||||
| 
 | ||||
| 
 | ||||
| function(conan_profile_detect_default) | ||||
|     message(STATUS "CMake-Conan: Checking if a default profile exists") | ||||
|     execute_process(COMMAND ${CONAN_COMMAND} profile path default | ||||
|                     RESULT_VARIABLE return_code | ||||
|                     OUTPUT_VARIABLE conan_stdout | ||||
|                     ERROR_VARIABLE conan_stderr | ||||
|                     ECHO_ERROR_VARIABLE    # show the text output regardless | ||||
|                     ECHO_OUTPUT_VARIABLE | ||||
|                     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) | ||||
|     if(NOT ${return_code} EQUAL "0") | ||||
|         message(STATUS "CMake-Conan: The default profile doesn't exist, detecting it.") | ||||
|         execute_process(COMMAND ${CONAN_COMMAND} profile detect | ||||
|             RESULT_VARIABLE return_code | ||||
|             OUTPUT_VARIABLE conan_stdout | ||||
|             ERROR_VARIABLE conan_stderr | ||||
|             ECHO_ERROR_VARIABLE    # show the text output regardless | ||||
|             ECHO_OUTPUT_VARIABLE | ||||
|             WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) | ||||
|     endif() | ||||
| endfunction() | ||||
| 
 | ||||
| 
 | ||||
| function(conan_install) | ||||
|     cmake_parse_arguments(ARGS CONAN_ARGS ${ARGN}) | ||||
|     set(CONAN_OUTPUT_FOLDER ${CMAKE_BINARY_DIR}/conan) | ||||
|     # Invoke "conan install" with the provided arguments | ||||
|     set(CONAN_ARGS ${CONAN_ARGS} -of=${CONAN_OUTPUT_FOLDER}) | ||||
|     message(STATUS "CMake-Conan: conan install ${CMAKE_SOURCE_DIR} ${CONAN_ARGS} ${ARGN}") | ||||
|     execute_process(COMMAND ${CONAN_COMMAND} install ${CMAKE_SOURCE_DIR} ${CONAN_ARGS} ${ARGN} --format=json | ||||
|                     RESULT_VARIABLE return_code | ||||
|                     OUTPUT_VARIABLE conan_stdout | ||||
|                     ERROR_VARIABLE conan_stderr | ||||
|                     ECHO_ERROR_VARIABLE    # show the text output regardless | ||||
|                     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) | ||||
|     if(NOT "${return_code}" STREQUAL "0") | ||||
|         message(FATAL_ERROR "Conan install failed='${return_code}'") | ||||
|     else() | ||||
|         # the files are generated in a folder that depends on the layout used, if | ||||
|         # one is specified, but we don't know a priori where this is. | ||||
|         # TODO: this can be made more robust if Conan can provide this in the json output | ||||
|         string(JSON CONAN_GENERATORS_FOLDER GET ${conan_stdout} graph nodes 0 generators_folder) | ||||
|         # message("conan stdout: ${conan_stdout}") | ||||
|         message(STATUS "CMake-Conan: CONAN_GENERATORS_FOLDER=${CONAN_GENERATORS_FOLDER}") | ||||
|         set_property(GLOBAL PROPERTY CONAN_GENERATORS_FOLDER "${CONAN_GENERATORS_FOLDER}") | ||||
|         # reconfigure on conanfile changes | ||||
|         string(JSON CONANFILE GET ${conan_stdout} graph nodes 0 label) | ||||
|         message(STATUS "CMake-Conan: CONANFILE=${CMAKE_SOURCE_DIR}/${CONANFILE}") | ||||
|         set_property(DIRECTORY ${CMAKE_SOURCE_DIR} APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/${CONANFILE}") | ||||
|         # success | ||||
|         set_property(GLOBAL PROPERTY CONAN_INSTALL_SUCCESS TRUE) | ||||
|     endif() | ||||
| endfunction() | ||||
| 
 | ||||
| 
 | ||||
| function(conan_get_version conan_command conan_current_version) | ||||
|     execute_process( | ||||
|         COMMAND ${conan_command} --version | ||||
|         OUTPUT_VARIABLE conan_output | ||||
|         RESULT_VARIABLE conan_result | ||||
|         OUTPUT_STRIP_TRAILING_WHITESPACE | ||||
|     ) | ||||
|     if(conan_result) | ||||
|         message(FATAL_ERROR "CMake-Conan: Error when trying to run Conan") | ||||
|     endif() | ||||
| 
 | ||||
|     string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" conan_version ${conan_output}) | ||||
|     set(${conan_current_version} ${conan_version} PARENT_SCOPE) | ||||
| endfunction() | ||||
| 
 | ||||
| 
 | ||||
| function(conan_version_check) | ||||
|     set(options ) | ||||
|     set(oneValueArgs MINIMUM CURRENT) | ||||
|     set(multiValueArgs ) | ||||
|     cmake_parse_arguments(CONAN_VERSION_CHECK | ||||
|         "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) | ||||
| 
 | ||||
|     if(NOT CONAN_VERSION_CHECK_MINIMUM) | ||||
|         message(FATAL_ERROR "CMake-Conan: Required parameter MINIMUM not set!") | ||||
|     endif() | ||||
|         if(NOT CONAN_VERSION_CHECK_CURRENT) | ||||
|         message(FATAL_ERROR "CMake-Conan: Required parameter CURRENT not set!") | ||||
|     endif() | ||||
| 
 | ||||
|     if(CONAN_VERSION_CHECK_CURRENT VERSION_LESS CONAN_VERSION_CHECK_MINIMUM) | ||||
|         message(FATAL_ERROR "CMake-Conan: Conan version must be ${CONAN_VERSION_CHECK_MINIMUM} or later") | ||||
|     endif() | ||||
| endfunction() | ||||
| 
 | ||||
| macro(construct_profile_argument argument_variable profile_list) | ||||
|     set(${argument_variable} "") | ||||
|     if("${profile_list}" STREQUAL "CONAN_HOST_PROFILE") | ||||
|         set(_arg_flag "--profile:host=") | ||||
|     elseif("${profile_list}" STREQUAL "CONAN_BUILD_PROFILE") | ||||
|         set(_arg_flag "--profile:build=") | ||||
|     endif() | ||||
| 
 | ||||
|     set(_profile_list "${${profile_list}}") | ||||
|     list(TRANSFORM _profile_list REPLACE "auto-cmake" "${CMAKE_BINARY_DIR}/conan_host_profile") | ||||
|     list(TRANSFORM _profile_list PREPEND ${_arg_flag}) | ||||
|     set(${argument_variable} ${_profile_list}) | ||||
| 
 | ||||
|     unset(_arg_flag) | ||||
|     unset(_profile_list) | ||||
| endmacro() | ||||
| 
 | ||||
| 
 | ||||
| macro(conan_provide_dependency method package_name) | ||||
|     set_property(GLOBAL PROPERTY CONAN_PROVIDE_DEPENDENCY_INVOKED TRUE) | ||||
|     get_property(CONAN_INSTALL_SUCCESS GLOBAL PROPERTY CONAN_INSTALL_SUCCESS) | ||||
|     if(NOT CONAN_INSTALL_SUCCESS) | ||||
|         find_program(CONAN_COMMAND "conan" REQUIRED) | ||||
|         conan_get_version(${CONAN_COMMAND} CONAN_CURRENT_VERSION) | ||||
|         conan_version_check(MINIMUM ${CONAN_MINIMUM_VERSION} CURRENT ${CONAN_CURRENT_VERSION}) | ||||
|         message(STATUS "CMake-Conan: first find_package() found. Installing dependencies with Conan") | ||||
|         if("default" IN_LIST CONAN_HOST_PROFILE OR "default" IN_LIST CONAN_BUILD_PROFILE) | ||||
|             conan_profile_detect_default() | ||||
|         endif() | ||||
|         if("auto-cmake" IN_LIST CONAN_HOST_PROFILE) | ||||
|             detect_host_profile(${CMAKE_BINARY_DIR}/conan_host_profile) | ||||
|         endif() | ||||
|         construct_profile_argument(_host_profile_flags CONAN_HOST_PROFILE) | ||||
|         construct_profile_argument(_build_profile_flags CONAN_BUILD_PROFILE) | ||||
|         get_property(_MULTICONFIG_GENERATOR GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) | ||||
|         if(NOT _MULTICONFIG_GENERATOR) | ||||
|             message(STATUS "CMake-Conan: Installing single configuration ${CMAKE_BUILD_TYPE}") | ||||
|             conan_install(${_host_profile_flags} ${_build_profile_flags} --build=missing -g CMakeDeps) | ||||
|         else() | ||||
|             message(STATUS "CMake-Conan: Installing both Debug and Release") | ||||
|             conan_install(${_host_profile_flags} ${_build_profile_flags} -s build_type=Release --build=missing -g CMakeDeps) | ||||
|             conan_install(${_host_profile_flags} ${_build_profile_flags} -s build_type=Debug --build=missing -g CMakeDeps) | ||||
|         endif() | ||||
|         unset(_MULTICONFIG_GENERATOR) | ||||
|     else() | ||||
|         message(STATUS "CMake-Conan: find_package(${ARGV1}) found, 'conan install' already ran") | ||||
|     endif() | ||||
| 
 | ||||
|     get_property(CONAN_GENERATORS_FOLDER GLOBAL PROPERTY CONAN_GENERATORS_FOLDER) | ||||
| 
 | ||||
|     # Ensure that we consider Conan-provided packages ahead of any other, | ||||
|     # irrespective of other settings that modify the search order or search paths | ||||
|     # This follows the guidelines from the find_package documentation | ||||
|     #  (https://cmake.org/cmake/help/latest/command/find_package.html): | ||||
|     #       find_package (<PackageName> PATHS paths... NO_DEFAULT_PATH) | ||||
|     #       find_package (<PackageName>) | ||||
| 
 | ||||
|     # Filter out `REQUIRED` from the argument list, as the first call may fail | ||||
|     set(_find_args "${ARGN}") | ||||
|     list(REMOVE_ITEM _find_args "REQUIRED") | ||||
|     if(NOT "MODULE" IN_LIST _find_args) | ||||
|         find_package(${package_name} ${_find_args} BYPASS_PROVIDER PATHS "${CONAN_GENERATORS_FOLDER}" NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) | ||||
|     endif() | ||||
| 
 | ||||
|     # Invoke find_package a second time - if the first call succeeded, | ||||
|     # this will simply reuse the result. If not, fall back to CMake default search | ||||
|     # behaviour, also allowing modules to be searched. | ||||
|     set(_cmake_module_path_orig "${CMAKE_MODULE_PATH}") | ||||
|     list(PREPEND CMAKE_MODULE_PATH "${CONAN_GENERATORS_FOLDER}") | ||||
|     if(NOT ${package_name}_FOUND) | ||||
|         find_package(${package_name} ${ARGN} BYPASS_PROVIDER) | ||||
|     endif() | ||||
| 
 | ||||
|     set(CMAKE_MODULE_PATH "${_cmake_module_path_orig}") | ||||
|     unset(_find_args) | ||||
|     unset(_cmake_module_path_orig) | ||||
|     unset(_host_profile_flags) | ||||
|     unset(_build_profile_flags) | ||||
| endmacro() | ||||
| 
 | ||||
| 
 | ||||
| cmake_language( | ||||
|   SET_DEPENDENCY_PROVIDER conan_provide_dependency | ||||
|   SUPPORTED_METHODS FIND_PACKAGE | ||||
| ) | ||||
| 
 | ||||
| macro(conan_provide_dependency_check) | ||||
|     set(_CONAN_PROVIDE_DEPENDENCY_INVOKED FALSE) | ||||
|     get_property(_CONAN_PROVIDE_DEPENDENCY_INVOKED GLOBAL PROPERTY CONAN_PROVIDE_DEPENDENCY_INVOKED) | ||||
|     if(NOT _CONAN_PROVIDE_DEPENDENCY_INVOKED) | ||||
|         message(WARNING "Conan is correctly configured as dependency provider, " | ||||
|                         "but Conan has not been invoked. Please add at least one " | ||||
|                         "call to `find_package()`.") | ||||
|         if(DEFINED CONAN_COMMAND) | ||||
|             # supress warning in case `CONAN_COMMAND` was specified but unused. | ||||
|             set(_CONAN_COMMAND ${CONAN_COMMAND}) | ||||
|             unset(_CONAN_COMMAND) | ||||
|         endif() | ||||
|     endif() | ||||
|     unset(_CONAN_PROVIDE_DEPENDENCY_INVOKED) | ||||
| endmacro() | ||||
| 
 | ||||
| # Add a deferred call at the end of processing the top-level directory | ||||
| # to check if the dependency provider was invoked at all. | ||||
| cmake_language(DEFER DIRECTORY "${CMAKE_SOURCE_DIR}" CALL conan_provide_dependency_check) | ||||
| 
 | ||||
| # Configurable variables for Conan profiles | ||||
| set(CONAN_HOST_PROFILE "default;auto-cmake" CACHE STRING "Conan host profile") | ||||
| set(CONAN_BUILD_PROFILE "default" CACHE STRING "Conan build profile") | ||||
|  | @ -0,0 +1,8 @@ | |||
| # This file is managed by Conan, contents will be overwritten. | ||||
| # To keep your changes, remove these comment lines, but the plugin won't be able to modify your requirements | ||||
| 
 | ||||
| requirements: | ||||
|   - "glfw/3.3.8" | ||||
|   - "glew/2.2.0" | ||||
|   - "imgui/1.89.9" | ||||
|   - "opengl/system" | ||||
|  | @ -0,0 +1,23 @@ | |||
| # This file is managed by Conan, contents will be overwritten. | ||||
| # To keep your changes, remove these comment lines, but the plugin won't be able to modify your requirements | ||||
| 
 | ||||
| from conan import ConanFile | ||||
| from conan.tools.cmake import cmake_layout, CMakeToolchain | ||||
| 
 | ||||
| class ConanApplication(ConanFile): | ||||
|     package_type = "application" | ||||
|     settings = "os", "compiler", "build_type", "arch" | ||||
|     generators = "CMakeDeps" | ||||
| 
 | ||||
|     def layout(self): | ||||
|         cmake_layout(self) | ||||
| 
 | ||||
|     def generate(self): | ||||
|         tc = CMakeToolchain(self) | ||||
|         tc.user_presets_path = False | ||||
|         tc.generate() | ||||
| 
 | ||||
|     def requirements(self): | ||||
|         requirements = self.conan_data.get('requirements', []) | ||||
|         for requirement in requirements: | ||||
|             self.requires(requirement) | ||||
							
								
								
									
										9
									
								
								imgui.h
								
								
								
								
							
							
						
						
									
										9
									
								
								imgui.h
								
								
								
								
							|  | @ -7,14 +7,9 @@ | |||
| 
 | ||||
| 
 | ||||
| #include "imgui/imgui.h" | ||||
| #include "imgui/imgui_impl_sdl3.h" | ||||
| #include "imgui/imgui_impl_opengl3.h" | ||||
| 
 | ||||
| #if defined(IMGUI_IMPL_OPENGL_ES2) | ||||
| #include <SDL3/SDL_opengles2.h> | ||||
| #else | ||||
| #include <SDL3/SDL_opengl.h> | ||||
| #endif | ||||
| #include "imgui/imgui_impl_opengl3_loader.h" | ||||
| #include "imgui/imgui_impl_glfw.h" | ||||
| 
 | ||||
| 
 | ||||
| #endif //KGE_IMGUI_H
 | ||||
|  |  | |||
|  | @ -0,0 +1,803 @@ | |||
| // dear imgui: Platform Backend for GLFW
 | ||||
| // This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
 | ||||
| // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
 | ||||
| // (Requires: GLFW 3.1+. Prefer GLFW 3.3+ or GLFW 3.4+ for full feature support.)
 | ||||
| 
 | ||||
| // Implemented features:
 | ||||
| //  [X] Platform: Clipboard support.
 | ||||
| //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
 | ||||
| //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
 | ||||
| //  [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 | ||||
| //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
 | ||||
| 
 | ||||
| // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 | ||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 | ||||
| // Learn about Dear ImGui:
 | ||||
| // - FAQ                  https://dearimgui.com/faq
 | ||||
| // - Getting Started      https://dearimgui.com/getting-started
 | ||||
| // - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
 | ||||
| // - Introduction, links and more at the top of imgui.cpp
 | ||||
| 
 | ||||
| // CHANGELOG
 | ||||
| // (minor and older changes stripped away, please see git history for details)
 | ||||
| //  2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609)
 | ||||
| //  2023-06-12: Accept glfwGetTime() not returning a monotonically increasing value. This seems to happens on some Windows setup when peripherals disconnect, and is likely to also happen on browser + Emscripten. (#6491)
 | ||||
| //  2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen on Windows ONLY, using a custom WndProc hook. (#2702)
 | ||||
| //  2023-03-16: Inputs: Fixed key modifiers handling on secondary viewports (docking branch). Broken on 2023/01/04. (#6248, #6034)
 | ||||
| //  2023-03-14: Emscripten: Avoid using glfwGetError() and glfwGetGamepadState() which are not correctly implemented in Emscripten emulation. (#6240)
 | ||||
| //  2023-02-03: Emscripten: Registering custom low-level mouse wheel handler to get more accurate scrolling impulses on Emscripten. (#4019, #6096)
 | ||||
| //  2023-01-04: Inputs: Fixed mods state on Linux when using Alt-GR text input (e.g. German keyboard layout), could lead to broken text input. Revert a 2022/01/17 change were we resumed using mods provided by GLFW, turns out they were faulty.
 | ||||
| //  2022-11-22: Perform a dummy glfwGetError() read to cancel missing names with glfwGetKeyName(). (#5908)
 | ||||
| //  2022-10-18: Perform a dummy glfwGetError() read to cancel missing mouse cursors errors. Using GLFW_VERSION_COMBINED directly. (#5785)
 | ||||
| //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 | ||||
| //  2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
 | ||||
| //  2022-09-01: Inputs: Honor GLFW_CURSOR_DISABLED by not setting mouse position *EDIT* Reverted 2023-07-18.
 | ||||
| //  2022-04-30: Inputs: Fixed ImGui_ImplGlfw_TranslateUntranslatedKey() for lower case letters on OSX.
 | ||||
| //  2022-03-23: Inputs: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11.
 | ||||
| //  2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after initializing backend.
 | ||||
| //  2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
 | ||||
| //  2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].
 | ||||
| //  2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
 | ||||
| //  2022-01-17: Inputs: always update key mods next and before key event (not in NewFrame) to fix input queue with very low framerates.
 | ||||
| //  2022-01-12: *BREAKING CHANGE*: Now using glfwSetCursorPosCallback(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetCursorPosCallback() and forward it to the backend via ImGui_ImplGlfw_CursorPosCallback().
 | ||||
| //  2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
 | ||||
| //  2022-01-05: Inputs: Converting GLFW untranslated keycodes back to translated keycodes (in the ImGui_ImplGlfw_KeyCallback() function) in order to match the behavior of every other backend, and facilitate the use of GLFW with lettered-shortcuts API.
 | ||||
| //  2021-08-17: *BREAKING CHANGE*: Now using glfwSetWindowFocusCallback() to calling io.AddFocusEvent(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() and forward it to the backend via ImGui_ImplGlfw_WindowFocusCallback().
 | ||||
| //  2021-07-29: *BREAKING CHANGE*: Now using glfwSetCursorEnterCallback(). MousePos is correctly reported when the host platform window is hovered but not focused. If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() callback and forward it to the backend via ImGui_ImplGlfw_CursorEnterCallback().
 | ||||
| //  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
 | ||||
| //  2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors.
 | ||||
| //  2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor).
 | ||||
| //  2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown.
 | ||||
| //  2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
 | ||||
| //  2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
 | ||||
| //  2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
 | ||||
| //  2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
 | ||||
| //  2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them.
 | ||||
| //  2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
 | ||||
| //  2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
 | ||||
| //  2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples.
 | ||||
| //  2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
 | ||||
| //  2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()).
 | ||||
| //  2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
 | ||||
| //  2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
 | ||||
| //  2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set.
 | ||||
| //  2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
 | ||||
| //  2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
 | ||||
| //  2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
 | ||||
| //  2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
 | ||||
| //  2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
 | ||||
| 
 | ||||
| #include "imgui.h" | ||||
| #ifndef IMGUI_DISABLE | ||||
| #include "imgui_impl_glfw.h" | ||||
| 
 | ||||
| // Clang warnings with -Weverything
 | ||||
| #if defined(__clang__) | ||||
| #pragma clang diagnostic push | ||||
| #pragma clang diagnostic ignored "-Wold-style-cast"     // warning: use of old-style cast
 | ||||
| #pragma clang diagnostic ignored "-Wsign-conversion"    // warning: implicit conversion changes signedness
 | ||||
| #endif | ||||
| 
 | ||||
| // GLFW
 | ||||
| #include <GLFW/glfw3.h> | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #undef APIENTRY | ||||
| #define GLFW_EXPOSE_NATIVE_WIN32 | ||||
| #include <GLFW/glfw3native.h>   // for glfwGetWin32Window()
 | ||||
| #endif | ||||
| #ifdef __APPLE__ | ||||
| #define GLFW_EXPOSE_NATIVE_COCOA | ||||
| #include <GLFW/glfw3native.h>   // for glfwGetCocoaWindow()
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __EMSCRIPTEN__ | ||||
| #include <emscripten.h> | ||||
| #include <emscripten/html5.h> | ||||
| #endif | ||||
| 
 | ||||
| // We gather version tests as define in order to easily see which features are version-dependent.
 | ||||
| #define GLFW_VERSION_COMBINED           (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION) | ||||
| #ifdef GLFW_RESIZE_NESW_CURSOR          // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
 | ||||
| #define GLFW_HAS_NEW_CURSORS            (GLFW_VERSION_COMBINED >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR
 | ||||
| #else | ||||
| #define GLFW_HAS_NEW_CURSORS            (0) | ||||
| #endif | ||||
| #define GLFW_HAS_GAMEPAD_API            (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetGamepadState() new api
 | ||||
| #define GLFW_HAS_GETKEYNAME             (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
 | ||||
| #define GLFW_HAS_GETERROR               (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError()
 | ||||
| 
 | ||||
| // GLFW data
 | ||||
| enum GlfwClientApi | ||||
| { | ||||
|     GlfwClientApi_Unknown, | ||||
|     GlfwClientApi_OpenGL, | ||||
|     GlfwClientApi_Vulkan | ||||
| }; | ||||
| 
 | ||||
| struct ImGui_ImplGlfw_Data | ||||
| { | ||||
|     GLFWwindow*             Window; | ||||
|     GlfwClientApi           ClientApi; | ||||
|     double                  Time; | ||||
|     GLFWwindow*             MouseWindow; | ||||
|     GLFWcursor*             MouseCursors[ImGuiMouseCursor_COUNT]; | ||||
|     ImVec2                  LastValidMousePos; | ||||
|     bool                    InstalledCallbacks; | ||||
|     bool                    CallbacksChainForAllWindows; | ||||
| 
 | ||||
|     // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
 | ||||
|     GLFWwindowfocusfun      PrevUserCallbackWindowFocus; | ||||
|     GLFWcursorposfun        PrevUserCallbackCursorPos; | ||||
|     GLFWcursorenterfun      PrevUserCallbackCursorEnter; | ||||
|     GLFWmousebuttonfun      PrevUserCallbackMousebutton; | ||||
|     GLFWscrollfun           PrevUserCallbackScroll; | ||||
|     GLFWkeyfun              PrevUserCallbackKey; | ||||
|     GLFWcharfun             PrevUserCallbackChar; | ||||
|     GLFWmonitorfun          PrevUserCallbackMonitor; | ||||
| #ifdef _WIN32 | ||||
|     WNDPROC                 GlfwWndProc; | ||||
| #endif | ||||
| 
 | ||||
|     ImGui_ImplGlfw_Data()   { memset((void*)this, 0, sizeof(*this)); } | ||||
| }; | ||||
| 
 | ||||
| // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
 | ||||
| // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
 | ||||
| // FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
 | ||||
| // - Because glfwPollEvents() process all windows and some events may be called outside of it, you will need to register your own callbacks
 | ||||
| //   (passing install_callbacks=false in ImGui_ImplGlfw_InitXXX functions), set the current dear imgui context and then call our callbacks.
 | ||||
| // - Otherwise we may need to store a GLFWWindow* -> ImGuiContext* map and handle this in the backend, adding a little bit of extra complexity to it.
 | ||||
| // FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
 | ||||
| static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() | ||||
| { | ||||
|     return ImGui::GetCurrentContext() ? (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; | ||||
| } | ||||
| 
 | ||||
| // Functions
 | ||||
| static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) | ||||
| { | ||||
|     return glfwGetClipboardString((GLFWwindow*)user_data); | ||||
| } | ||||
| 
 | ||||
| static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) | ||||
| { | ||||
|     glfwSetClipboardString((GLFWwindow*)user_data, text); | ||||
| } | ||||
| 
 | ||||
| static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key) | ||||
| { | ||||
|     switch (key) | ||||
|     { | ||||
|         case GLFW_KEY_TAB: return ImGuiKey_Tab; | ||||
|         case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow; | ||||
|         case GLFW_KEY_RIGHT: return ImGuiKey_RightArrow; | ||||
|         case GLFW_KEY_UP: return ImGuiKey_UpArrow; | ||||
|         case GLFW_KEY_DOWN: return ImGuiKey_DownArrow; | ||||
|         case GLFW_KEY_PAGE_UP: return ImGuiKey_PageUp; | ||||
|         case GLFW_KEY_PAGE_DOWN: return ImGuiKey_PageDown; | ||||
|         case GLFW_KEY_HOME: return ImGuiKey_Home; | ||||
|         case GLFW_KEY_END: return ImGuiKey_End; | ||||
|         case GLFW_KEY_INSERT: return ImGuiKey_Insert; | ||||
|         case GLFW_KEY_DELETE: return ImGuiKey_Delete; | ||||
|         case GLFW_KEY_BACKSPACE: return ImGuiKey_Backspace; | ||||
|         case GLFW_KEY_SPACE: return ImGuiKey_Space; | ||||
|         case GLFW_KEY_ENTER: return ImGuiKey_Enter; | ||||
|         case GLFW_KEY_ESCAPE: return ImGuiKey_Escape; | ||||
|         case GLFW_KEY_APOSTROPHE: return ImGuiKey_Apostrophe; | ||||
|         case GLFW_KEY_COMMA: return ImGuiKey_Comma; | ||||
|         case GLFW_KEY_MINUS: return ImGuiKey_Minus; | ||||
|         case GLFW_KEY_PERIOD: return ImGuiKey_Period; | ||||
|         case GLFW_KEY_SLASH: return ImGuiKey_Slash; | ||||
|         case GLFW_KEY_SEMICOLON: return ImGuiKey_Semicolon; | ||||
|         case GLFW_KEY_EQUAL: return ImGuiKey_Equal; | ||||
|         case GLFW_KEY_LEFT_BRACKET: return ImGuiKey_LeftBracket; | ||||
|         case GLFW_KEY_BACKSLASH: return ImGuiKey_Backslash; | ||||
|         case GLFW_KEY_RIGHT_BRACKET: return ImGuiKey_RightBracket; | ||||
|         case GLFW_KEY_GRAVE_ACCENT: return ImGuiKey_GraveAccent; | ||||
|         case GLFW_KEY_CAPS_LOCK: return ImGuiKey_CapsLock; | ||||
|         case GLFW_KEY_SCROLL_LOCK: return ImGuiKey_ScrollLock; | ||||
|         case GLFW_KEY_NUM_LOCK: return ImGuiKey_NumLock; | ||||
|         case GLFW_KEY_PRINT_SCREEN: return ImGuiKey_PrintScreen; | ||||
|         case GLFW_KEY_PAUSE: return ImGuiKey_Pause; | ||||
|         case GLFW_KEY_KP_0: return ImGuiKey_Keypad0; | ||||
|         case GLFW_KEY_KP_1: return ImGuiKey_Keypad1; | ||||
|         case GLFW_KEY_KP_2: return ImGuiKey_Keypad2; | ||||
|         case GLFW_KEY_KP_3: return ImGuiKey_Keypad3; | ||||
|         case GLFW_KEY_KP_4: return ImGuiKey_Keypad4; | ||||
|         case GLFW_KEY_KP_5: return ImGuiKey_Keypad5; | ||||
|         case GLFW_KEY_KP_6: return ImGuiKey_Keypad6; | ||||
|         case GLFW_KEY_KP_7: return ImGuiKey_Keypad7; | ||||
|         case GLFW_KEY_KP_8: return ImGuiKey_Keypad8; | ||||
|         case GLFW_KEY_KP_9: return ImGuiKey_Keypad9; | ||||
|         case GLFW_KEY_KP_DECIMAL: return ImGuiKey_KeypadDecimal; | ||||
|         case GLFW_KEY_KP_DIVIDE: return ImGuiKey_KeypadDivide; | ||||
|         case GLFW_KEY_KP_MULTIPLY: return ImGuiKey_KeypadMultiply; | ||||
|         case GLFW_KEY_KP_SUBTRACT: return ImGuiKey_KeypadSubtract; | ||||
|         case GLFW_KEY_KP_ADD: return ImGuiKey_KeypadAdd; | ||||
|         case GLFW_KEY_KP_ENTER: return ImGuiKey_KeypadEnter; | ||||
|         case GLFW_KEY_KP_EQUAL: return ImGuiKey_KeypadEqual; | ||||
|         case GLFW_KEY_LEFT_SHIFT: return ImGuiKey_LeftShift; | ||||
|         case GLFW_KEY_LEFT_CONTROL: return ImGuiKey_LeftCtrl; | ||||
|         case GLFW_KEY_LEFT_ALT: return ImGuiKey_LeftAlt; | ||||
|         case GLFW_KEY_LEFT_SUPER: return ImGuiKey_LeftSuper; | ||||
|         case GLFW_KEY_RIGHT_SHIFT: return ImGuiKey_RightShift; | ||||
|         case GLFW_KEY_RIGHT_CONTROL: return ImGuiKey_RightCtrl; | ||||
|         case GLFW_KEY_RIGHT_ALT: return ImGuiKey_RightAlt; | ||||
|         case GLFW_KEY_RIGHT_SUPER: return ImGuiKey_RightSuper; | ||||
|         case GLFW_KEY_MENU: return ImGuiKey_Menu; | ||||
|         case GLFW_KEY_0: return ImGuiKey_0; | ||||
|         case GLFW_KEY_1: return ImGuiKey_1; | ||||
|         case GLFW_KEY_2: return ImGuiKey_2; | ||||
|         case GLFW_KEY_3: return ImGuiKey_3; | ||||
|         case GLFW_KEY_4: return ImGuiKey_4; | ||||
|         case GLFW_KEY_5: return ImGuiKey_5; | ||||
|         case GLFW_KEY_6: return ImGuiKey_6; | ||||
|         case GLFW_KEY_7: return ImGuiKey_7; | ||||
|         case GLFW_KEY_8: return ImGuiKey_8; | ||||
|         case GLFW_KEY_9: return ImGuiKey_9; | ||||
|         case GLFW_KEY_A: return ImGuiKey_A; | ||||
|         case GLFW_KEY_B: return ImGuiKey_B; | ||||
|         case GLFW_KEY_C: return ImGuiKey_C; | ||||
|         case GLFW_KEY_D: return ImGuiKey_D; | ||||
|         case GLFW_KEY_E: return ImGuiKey_E; | ||||
|         case GLFW_KEY_F: return ImGuiKey_F; | ||||
|         case GLFW_KEY_G: return ImGuiKey_G; | ||||
|         case GLFW_KEY_H: return ImGuiKey_H; | ||||
|         case GLFW_KEY_I: return ImGuiKey_I; | ||||
|         case GLFW_KEY_J: return ImGuiKey_J; | ||||
|         case GLFW_KEY_K: return ImGuiKey_K; | ||||
|         case GLFW_KEY_L: return ImGuiKey_L; | ||||
|         case GLFW_KEY_M: return ImGuiKey_M; | ||||
|         case GLFW_KEY_N: return ImGuiKey_N; | ||||
|         case GLFW_KEY_O: return ImGuiKey_O; | ||||
|         case GLFW_KEY_P: return ImGuiKey_P; | ||||
|         case GLFW_KEY_Q: return ImGuiKey_Q; | ||||
|         case GLFW_KEY_R: return ImGuiKey_R; | ||||
|         case GLFW_KEY_S: return ImGuiKey_S; | ||||
|         case GLFW_KEY_T: return ImGuiKey_T; | ||||
|         case GLFW_KEY_U: return ImGuiKey_U; | ||||
|         case GLFW_KEY_V: return ImGuiKey_V; | ||||
|         case GLFW_KEY_W: return ImGuiKey_W; | ||||
|         case GLFW_KEY_X: return ImGuiKey_X; | ||||
|         case GLFW_KEY_Y: return ImGuiKey_Y; | ||||
|         case GLFW_KEY_Z: return ImGuiKey_Z; | ||||
|         case GLFW_KEY_F1: return ImGuiKey_F1; | ||||
|         case GLFW_KEY_F2: return ImGuiKey_F2; | ||||
|         case GLFW_KEY_F3: return ImGuiKey_F3; | ||||
|         case GLFW_KEY_F4: return ImGuiKey_F4; | ||||
|         case GLFW_KEY_F5: return ImGuiKey_F5; | ||||
|         case GLFW_KEY_F6: return ImGuiKey_F6; | ||||
|         case GLFW_KEY_F7: return ImGuiKey_F7; | ||||
|         case GLFW_KEY_F8: return ImGuiKey_F8; | ||||
|         case GLFW_KEY_F9: return ImGuiKey_F9; | ||||
|         case GLFW_KEY_F10: return ImGuiKey_F10; | ||||
|         case GLFW_KEY_F11: return ImGuiKey_F11; | ||||
|         case GLFW_KEY_F12: return ImGuiKey_F12; | ||||
|         default: return ImGuiKey_None; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW
 | ||||
| // See https://github.com/ocornut/imgui/issues/6034 and https://github.com/glfw/glfw/issues/1630
 | ||||
| static void ImGui_ImplGlfw_UpdateKeyModifiers(GLFWwindow* window) | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     io.AddKeyEvent(ImGuiMod_Ctrl,  (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS)); | ||||
|     io.AddKeyEvent(ImGuiMod_Shift, (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT)   == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT)   == GLFW_PRESS)); | ||||
|     io.AddKeyEvent(ImGuiMod_Alt,   (glfwGetKey(window, GLFW_KEY_LEFT_ALT)     == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_ALT)     == GLFW_PRESS)); | ||||
|     io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(window, GLFW_KEY_LEFT_SUPER)   == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SUPER)   == GLFW_PRESS)); | ||||
| } | ||||
| 
 | ||||
| static bool ImGui_ImplGlfw_ShouldChainCallback(GLFWwindow* window) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     return bd->CallbacksChainForAllWindows ? true : (window == bd->Window); | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) | ||||
|         bd->PrevUserCallbackMousebutton(window, button, action, mods); | ||||
| 
 | ||||
|     ImGui_ImplGlfw_UpdateKeyModifiers(window); | ||||
| 
 | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     if (button >= 0 && button < ImGuiMouseButton_COUNT) | ||||
|         io.AddMouseButtonEvent(button, action == GLFW_PRESS); | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) | ||||
|         bd->PrevUserCallbackScroll(window, xoffset, yoffset); | ||||
| 
 | ||||
| #ifdef __EMSCRIPTEN__ | ||||
|     // Ignore GLFW events: will be processed in ImGui_ImplEmscripten_WheelCallback().
 | ||||
|     return; | ||||
| #endif | ||||
| 
 | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     io.AddMouseWheelEvent((float)xoffset, (float)yoffset); | ||||
| } | ||||
| 
 | ||||
| static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) | ||||
| { | ||||
| #if GLFW_HAS_GETKEYNAME && !defined(__EMSCRIPTEN__) | ||||
|     // GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult.
 | ||||
|     // (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently)
 | ||||
|     // See https://github.com/glfw/glfw/issues/1502 for details.
 | ||||
|     // Adding a workaround to undo this (so our keys are translated->untranslated->translated, likely a lossy process).
 | ||||
|     // This won't cover edge cases but this is at least going to cover common cases.
 | ||||
|     if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_EQUAL) | ||||
|         return key; | ||||
|     GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr); | ||||
|     const char* key_name = glfwGetKeyName(key, scancode); | ||||
|     glfwSetErrorCallback(prev_error_callback); | ||||
| #if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908)
 | ||||
|     (void)glfwGetError(nullptr); | ||||
| #endif | ||||
|     if (key_name && key_name[0] != 0 && key_name[1] == 0) | ||||
|     { | ||||
|         const char char_names[] = "`-=[]\\,;\'./"; | ||||
|         const int char_keys[] = { GLFW_KEY_GRAVE_ACCENT, GLFW_KEY_MINUS, GLFW_KEY_EQUAL, GLFW_KEY_LEFT_BRACKET, GLFW_KEY_RIGHT_BRACKET, GLFW_KEY_BACKSLASH, GLFW_KEY_COMMA, GLFW_KEY_SEMICOLON, GLFW_KEY_APOSTROPHE, GLFW_KEY_PERIOD, GLFW_KEY_SLASH, 0 }; | ||||
|         IM_ASSERT(IM_ARRAYSIZE(char_names) == IM_ARRAYSIZE(char_keys)); | ||||
|         if (key_name[0] >= '0' && key_name[0] <= '9')               { key = GLFW_KEY_0 + (key_name[0] - '0'); } | ||||
|         else if (key_name[0] >= 'A' && key_name[0] <= 'Z')          { key = GLFW_KEY_A + (key_name[0] - 'A'); } | ||||
|         else if (key_name[0] >= 'a' && key_name[0] <= 'z')          { key = GLFW_KEY_A + (key_name[0] - 'a'); } | ||||
|         else if (const char* p = strchr(char_names, key_name[0]))   { key = char_keys[p - char_names]; } | ||||
|     } | ||||
|     // if (action == GLFW_PRESS) printf("key %d scancode %d name '%s'\n", key, scancode, key_name);
 | ||||
| #else | ||||
|     IM_UNUSED(scancode); | ||||
| #endif | ||||
|     return key; | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, int action, int mods) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     if (bd->PrevUserCallbackKey != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) | ||||
|         bd->PrevUserCallbackKey(window, keycode, scancode, action, mods); | ||||
| 
 | ||||
|     if (action != GLFW_PRESS && action != GLFW_RELEASE) | ||||
|         return; | ||||
| 
 | ||||
|     ImGui_ImplGlfw_UpdateKeyModifiers(window); | ||||
| 
 | ||||
|     keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode); | ||||
| 
 | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode); | ||||
|     io.AddKeyEvent(imgui_key, (action == GLFW_PRESS)); | ||||
|     io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
 | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) | ||||
|         bd->PrevUserCallbackWindowFocus(window, focused); | ||||
| 
 | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     io.AddFocusEvent(focused != 0); | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) | ||||
|         bd->PrevUserCallbackCursorPos(window, x, y); | ||||
| 
 | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     io.AddMousePosEvent((float)x, (float)y); | ||||
|     bd->LastValidMousePos = ImVec2((float)x, (float)y); | ||||
| } | ||||
| 
 | ||||
| // Workaround: X11 seems to send spurious Leave/Enter events which would make us lose our position,
 | ||||
| // so we back it up and restore on Leave/Enter (see https://github.com/ocornut/imgui/issues/4984)
 | ||||
| void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     if (bd->PrevUserCallbackCursorEnter != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) | ||||
|         bd->PrevUserCallbackCursorEnter(window, entered); | ||||
| 
 | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     if (entered) | ||||
|     { | ||||
|         bd->MouseWindow = window; | ||||
|         io.AddMousePosEvent(bd->LastValidMousePos.x, bd->LastValidMousePos.y); | ||||
|     } | ||||
|     else if (!entered && bd->MouseWindow == window) | ||||
|     { | ||||
|         bd->LastValidMousePos = io.MousePos; | ||||
|         bd->MouseWindow = nullptr; | ||||
|         io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     if (bd->PrevUserCallbackChar != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) | ||||
|         bd->PrevUserCallbackChar(window, c); | ||||
| 
 | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     io.AddInputCharacter(c); | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int) | ||||
| { | ||||
| 	// Unused in 'master' branch but 'docking' branch will use this, so we declare it ahead of it so if you have to install callbacks you can install this one too.
 | ||||
| } | ||||
| 
 | ||||
| #ifdef __EMSCRIPTEN__ | ||||
| static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*) | ||||
| { | ||||
|     // Mimic Emscripten_HandleWheel() in SDL.
 | ||||
|     // Corresponding equivalent in GLFW JS emulation layer has incorrect quantizing preventing small values. See #6096
 | ||||
|     float multiplier = 0.0f; | ||||
|     if (ev->deltaMode == DOM_DELTA_PIXEL)       { multiplier = 1.0f / 100.0f; } // 100 pixels make up a step.
 | ||||
|     else if (ev->deltaMode == DOM_DELTA_LINE)   { multiplier = 1.0f / 3.0f; }   // 3 lines make up a step.
 | ||||
|     else if (ev->deltaMode == DOM_DELTA_PAGE)   { multiplier = 80.0f; }         // A page makes up 80 steps.
 | ||||
|     float wheel_x = ev->deltaX * -multiplier; | ||||
|     float wheel_y = ev->deltaY * -multiplier; | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     io.AddMouseWheelEvent(wheel_x, wheel_y); | ||||
|     //IMGUI_DEBUG_LOG("[Emsc] mode %d dx: %.2f, dy: %.2f, dz: %.2f --> feed %.2f %.2f\n", (int)ev->deltaMode, ev->deltaX, ev->deltaY, ev->deltaZ, wheel_x, wheel_y);
 | ||||
|     return EM_TRUE; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| // GLFW doesn't allow to distinguish Mouse vs TouchScreen vs Pen.
 | ||||
| // Add support for Win32 (based on imgui_impl_win32), because we rely on _TouchScreen info to trickle inputs differently.
 | ||||
| static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo() | ||||
| { | ||||
|     LPARAM extra_info = ::GetMessageExtraInfo(); | ||||
|     if ((extra_info & 0xFFFFFF80) == 0xFF515700) | ||||
|         return ImGuiMouseSource_Pen; | ||||
|     if ((extra_info & 0xFFFFFF80) == 0xFF515780) | ||||
|         return ImGuiMouseSource_TouchScreen; | ||||
|     return ImGuiMouseSource_Mouse; | ||||
| } | ||||
| static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     switch (msg) | ||||
|     { | ||||
|     case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: | ||||
|     case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_LBUTTONUP: | ||||
|     case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP: | ||||
|     case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP: | ||||
|     case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONUP: | ||||
|         ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo()); | ||||
|         break; | ||||
|     } | ||||
|     return ::CallWindowProc(bd->GlfwWndProc, hWnd, msg, wParam, lParam); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     IM_ASSERT(bd->InstalledCallbacks == false && "Callbacks already installed!"); | ||||
|     IM_ASSERT(bd->Window == window); | ||||
| 
 | ||||
|     bd->PrevUserCallbackWindowFocus = glfwSetWindowFocusCallback(window, ImGui_ImplGlfw_WindowFocusCallback); | ||||
|     bd->PrevUserCallbackCursorEnter = glfwSetCursorEnterCallback(window, ImGui_ImplGlfw_CursorEnterCallback); | ||||
|     bd->PrevUserCallbackCursorPos = glfwSetCursorPosCallback(window, ImGui_ImplGlfw_CursorPosCallback); | ||||
|     bd->PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); | ||||
|     bd->PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); | ||||
|     bd->PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); | ||||
|     bd->PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); | ||||
|     bd->PrevUserCallbackMonitor = glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback); | ||||
|     bd->InstalledCallbacks = true; | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     IM_ASSERT(bd->InstalledCallbacks == true && "Callbacks not installed!"); | ||||
|     IM_ASSERT(bd->Window == window); | ||||
| 
 | ||||
|     glfwSetWindowFocusCallback(window, bd->PrevUserCallbackWindowFocus); | ||||
|     glfwSetCursorEnterCallback(window, bd->PrevUserCallbackCursorEnter); | ||||
|     glfwSetCursorPosCallback(window, bd->PrevUserCallbackCursorPos); | ||||
|     glfwSetMouseButtonCallback(window, bd->PrevUserCallbackMousebutton); | ||||
|     glfwSetScrollCallback(window, bd->PrevUserCallbackScroll); | ||||
|     glfwSetKeyCallback(window, bd->PrevUserCallbackKey); | ||||
|     glfwSetCharCallback(window, bd->PrevUserCallbackChar); | ||||
|     glfwSetMonitorCallback(bd->PrevUserCallbackMonitor); | ||||
|     bd->InstalledCallbacks = false; | ||||
|     bd->PrevUserCallbackWindowFocus = nullptr; | ||||
|     bd->PrevUserCallbackCursorEnter = nullptr; | ||||
|     bd->PrevUserCallbackCursorPos = nullptr; | ||||
|     bd->PrevUserCallbackMousebutton = nullptr; | ||||
|     bd->PrevUserCallbackScroll = nullptr; | ||||
|     bd->PrevUserCallbackKey = nullptr; | ||||
|     bd->PrevUserCallbackChar = nullptr; | ||||
|     bd->PrevUserCallbackMonitor = nullptr; | ||||
| } | ||||
| 
 | ||||
| // Set to 'true' to enable chaining installed callbacks for all windows (including secondary viewports created by backends or by user.
 | ||||
| // This is 'false' by default meaning we only chain callbacks for the main viewport.
 | ||||
| // We cannot set this to 'true' by default because user callbacks code may be not testing the 'window' parameter of their callback.
 | ||||
| // If you set this to 'true' your user callback code will need to make sure you are testing the 'window' parameter.
 | ||||
| void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows) | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     bd->CallbacksChainForAllWindows = chain_for_all_windows; | ||||
| } | ||||
| 
 | ||||
| static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); | ||||
|     //printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED);
 | ||||
| 
 | ||||
|     // Setup backend capabilities flags
 | ||||
|     ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)(); | ||||
|     io.BackendPlatformUserData = (void*)bd; | ||||
|     io.BackendPlatformName = "imgui_impl_glfw"; | ||||
|     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;         // We can honor GetMouseCursor() values (optional)
 | ||||
|     io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;          // We can honor io.WantSetMousePos requests (optional, rarely used)
 | ||||
| 
 | ||||
|     bd->Window = window; | ||||
|     bd->Time = 0.0; | ||||
| 
 | ||||
|     io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; | ||||
|     io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; | ||||
|     io.ClipboardUserData = bd->Window; | ||||
| 
 | ||||
|     // Create mouse cursors
 | ||||
|     // (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
 | ||||
|     // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting.
 | ||||
|     // Missing cursors will return nullptr and our _UpdateMouseCursor() function will use the Arrow cursor instead.)
 | ||||
|     GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); | ||||
| #if GLFW_HAS_NEW_CURSORS | ||||
|     bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_RESIZE_ALL_CURSOR); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_RESIZE_NESW_CURSOR); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_NOT_ALLOWED_CURSOR); | ||||
| #else | ||||
|     bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); | ||||
|     bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); | ||||
| #endif | ||||
|     glfwSetErrorCallback(prev_error_callback); | ||||
| #if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908)
 | ||||
|     (void)glfwGetError(nullptr); | ||||
| #endif | ||||
| 
 | ||||
|     // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
 | ||||
|     if (install_callbacks) | ||||
|         ImGui_ImplGlfw_InstallCallbacks(window); | ||||
|     // Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
 | ||||
|     // We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
 | ||||
|     // FIXME: May break chaining in case user registered their own Emscripten callback?
 | ||||
| #ifdef __EMSCRIPTEN__ | ||||
|     emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, ImGui_ImplEmscripten_WheelCallback); | ||||
| #endif | ||||
| 
 | ||||
|     // Set platform dependent data in viewport
 | ||||
|     ImGuiViewport* main_viewport = ImGui::GetMainViewport(); | ||||
| #ifdef _WIN32 | ||||
|     main_viewport->PlatformHandleRaw = glfwGetWin32Window(bd->Window); | ||||
| #elif defined(__APPLE__) | ||||
|     main_viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(bd->Window); | ||||
| #else | ||||
|     IM_UNUSED(main_viewport); | ||||
| #endif | ||||
| 
 | ||||
|     // Windows: register a WndProc hook so we can intercept some messages.
 | ||||
| #ifdef _WIN32 | ||||
|     bd->GlfwWndProc = (WNDPROC)::GetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC); | ||||
|     IM_ASSERT(bd->GlfwWndProc != nullptr); | ||||
|     ::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc); | ||||
| #endif | ||||
| 
 | ||||
|     bd->ClientApi = client_api; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks) | ||||
| { | ||||
|     return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_OpenGL); | ||||
| } | ||||
| 
 | ||||
| bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks) | ||||
| { | ||||
|     return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Vulkan); | ||||
| } | ||||
| 
 | ||||
| bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks) | ||||
| { | ||||
|     return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Unknown); | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplGlfw_Shutdown() | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
| 
 | ||||
|     if (bd->InstalledCallbacks) | ||||
|         ImGui_ImplGlfw_RestoreCallbacks(bd->Window); | ||||
| #ifdef __EMSCRIPTEN__ | ||||
|     emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr); | ||||
| #endif | ||||
| 
 | ||||
|     for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) | ||||
|         glfwDestroyCursor(bd->MouseCursors[cursor_n]); | ||||
| 
 | ||||
|     // Windows: register a WndProc hook so we can intercept some messages.
 | ||||
| #ifdef _WIN32 | ||||
|     ImGuiViewport* main_viewport = ImGui::GetMainViewport(); | ||||
|     ::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->GlfwWndProc); | ||||
|     bd->GlfwWndProc = nullptr; | ||||
| #endif | ||||
| 
 | ||||
|     io.BackendPlatformName = nullptr; | ||||
|     io.BackendPlatformUserData = nullptr; | ||||
|     io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad); | ||||
|     IM_DELETE(bd); | ||||
| } | ||||
| 
 | ||||
| static void ImGui_ImplGlfw_UpdateMouseData() | ||||
| { | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
| 
 | ||||
| 
 | ||||
|     // (those braces are here to reduce diff with multi-viewports support in 'docking' branch)
 | ||||
|     { | ||||
|         GLFWwindow* window = bd->Window; | ||||
| 
 | ||||
| #ifdef __EMSCRIPTEN__ | ||||
|         const bool is_window_focused = true; | ||||
| #else | ||||
|         const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0; | ||||
| #endif | ||||
|         if (is_window_focused) | ||||
|         { | ||||
|             // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
 | ||||
|             if (io.WantSetMousePos) | ||||
|                 glfwSetCursorPos(window, (double)io.MousePos.x, (double)io.MousePos.y); | ||||
| 
 | ||||
|             // (Optional) Fallback to provide mouse position when focused (ImGui_ImplGlfw_CursorPosCallback already provides this when hovered or captured)
 | ||||
|             if (bd->MouseWindow == nullptr) | ||||
|             { | ||||
|                 double mouse_x, mouse_y; | ||||
|                 glfwGetCursorPos(window, &mouse_x, &mouse_y); | ||||
|                 bd->LastValidMousePos = ImVec2((float)mouse_x, (float)mouse_y); | ||||
|                 io.AddMousePosEvent((float)mouse_x, (float)mouse_y); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void ImGui_ImplGlfw_UpdateMouseCursor() | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) | ||||
|         return; | ||||
| 
 | ||||
|     ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); | ||||
|     // (those braces are here to reduce diff with multi-viewports support in 'docking' branch)
 | ||||
|     { | ||||
|         GLFWwindow* window = bd->Window; | ||||
|         if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) | ||||
|         { | ||||
|             // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
 | ||||
|             glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // Show OS mouse cursor
 | ||||
|             // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
 | ||||
|             glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]); | ||||
|             glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Update gamepad inputs
 | ||||
| static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v  > 1.0f ? 1.0f : v; } | ||||
| static void ImGui_ImplGlfw_UpdateGamepads() | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
 | ||||
|         return; | ||||
| 
 | ||||
|     io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; | ||||
| #if GLFW_HAS_GAMEPAD_API && !defined(__EMSCRIPTEN__) | ||||
|     GLFWgamepadstate gamepad; | ||||
|     if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad)) | ||||
|         return; | ||||
|     #define MAP_BUTTON(KEY_NO, BUTTON_NO, _UNUSED)          do { io.AddKeyEvent(KEY_NO, gamepad.buttons[BUTTON_NO] != 0); } while (0) | ||||
|     #define MAP_ANALOG(KEY_NO, AXIS_NO, _UNUSED, V0, V1)    do { float v = gamepad.axes[AXIS_NO]; v = (v - V0) / (V1 - V0); io.AddKeyAnalogEvent(KEY_NO, v > 0.10f, Saturate(v)); } while (0) | ||||
| #else | ||||
|     int axes_count = 0, buttons_count = 0; | ||||
|     const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count); | ||||
|     const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count); | ||||
|     if (axes_count == 0 || buttons_count == 0) | ||||
|         return; | ||||
|     #define MAP_BUTTON(KEY_NO, _UNUSED, BUTTON_NO)          do { io.AddKeyEvent(KEY_NO, (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS)); } while (0) | ||||
|     #define MAP_ANALOG(KEY_NO, _UNUSED, AXIS_NO, V0, V1)    do { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); io.AddKeyAnalogEvent(KEY_NO, v > 0.10f, Saturate(v)); } while (0) | ||||
| #endif | ||||
|     io.BackendFlags |= ImGuiBackendFlags_HasGamepad; | ||||
|     MAP_BUTTON(ImGuiKey_GamepadStart,       GLFW_GAMEPAD_BUTTON_START,          7); | ||||
|     MAP_BUTTON(ImGuiKey_GamepadBack,        GLFW_GAMEPAD_BUTTON_BACK,           6); | ||||
|     MAP_BUTTON(ImGuiKey_GamepadFaceLeft,    GLFW_GAMEPAD_BUTTON_X,              2);     // Xbox X, PS Square
 | ||||
|     MAP_BUTTON(ImGuiKey_GamepadFaceRight,   GLFW_GAMEPAD_BUTTON_B,              1);     // Xbox B, PS Circle
 | ||||
|     MAP_BUTTON(ImGuiKey_GamepadFaceUp,      GLFW_GAMEPAD_BUTTON_Y,              3);     // Xbox Y, PS Triangle
 | ||||
|     MAP_BUTTON(ImGuiKey_GamepadFaceDown,    GLFW_GAMEPAD_BUTTON_A,              0);     // Xbox A, PS Cross
 | ||||
|     MAP_BUTTON(ImGuiKey_GamepadDpadLeft,    GLFW_GAMEPAD_BUTTON_DPAD_LEFT,      13); | ||||
|     MAP_BUTTON(ImGuiKey_GamepadDpadRight,   GLFW_GAMEPAD_BUTTON_DPAD_RIGHT,     11); | ||||
|     MAP_BUTTON(ImGuiKey_GamepadDpadUp,      GLFW_GAMEPAD_BUTTON_DPAD_UP,        10); | ||||
|     MAP_BUTTON(ImGuiKey_GamepadDpadDown,    GLFW_GAMEPAD_BUTTON_DPAD_DOWN,      12); | ||||
|     MAP_BUTTON(ImGuiKey_GamepadL1,          GLFW_GAMEPAD_BUTTON_LEFT_BUMPER,    4); | ||||
|     MAP_BUTTON(ImGuiKey_GamepadR1,          GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER,   5); | ||||
|     MAP_ANALOG(ImGuiKey_GamepadL2,          GLFW_GAMEPAD_AXIS_LEFT_TRIGGER,     4,      -0.75f,  +1.0f); | ||||
|     MAP_ANALOG(ImGuiKey_GamepadR2,          GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER,    5,      -0.75f,  +1.0f); | ||||
|     MAP_BUTTON(ImGuiKey_GamepadL3,          GLFW_GAMEPAD_BUTTON_LEFT_THUMB,     8); | ||||
|     MAP_BUTTON(ImGuiKey_GamepadR3,          GLFW_GAMEPAD_BUTTON_RIGHT_THUMB,    9); | ||||
|     MAP_ANALOG(ImGuiKey_GamepadLStickLeft,  GLFW_GAMEPAD_AXIS_LEFT_X,           0,      -0.25f,  -1.0f); | ||||
|     MAP_ANALOG(ImGuiKey_GamepadLStickRight, GLFW_GAMEPAD_AXIS_LEFT_X,           0,      +0.25f,  +1.0f); | ||||
|     MAP_ANALOG(ImGuiKey_GamepadLStickUp,    GLFW_GAMEPAD_AXIS_LEFT_Y,           1,      -0.25f,  -1.0f); | ||||
|     MAP_ANALOG(ImGuiKey_GamepadLStickDown,  GLFW_GAMEPAD_AXIS_LEFT_Y,           1,      +0.25f,  +1.0f); | ||||
|     MAP_ANALOG(ImGuiKey_GamepadRStickLeft,  GLFW_GAMEPAD_AXIS_RIGHT_X,          2,      -0.25f,  -1.0f); | ||||
|     MAP_ANALOG(ImGuiKey_GamepadRStickRight, GLFW_GAMEPAD_AXIS_RIGHT_X,          2,      +0.25f,  +1.0f); | ||||
|     MAP_ANALOG(ImGuiKey_GamepadRStickUp,    GLFW_GAMEPAD_AXIS_RIGHT_Y,          3,      -0.25f,  -1.0f); | ||||
|     MAP_ANALOG(ImGuiKey_GamepadRStickDown,  GLFW_GAMEPAD_AXIS_RIGHT_Y,          3,      +0.25f,  +1.0f); | ||||
|     #undef MAP_BUTTON | ||||
|     #undef MAP_ANALOG | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplGlfw_NewFrame() | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||
|     IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?"); | ||||
| 
 | ||||
|     // Setup display size (every frame to accommodate for window resizing)
 | ||||
|     int w, h; | ||||
|     int display_w, display_h; | ||||
|     glfwGetWindowSize(bd->Window, &w, &h); | ||||
|     glfwGetFramebufferSize(bd->Window, &display_w, &display_h); | ||||
|     io.DisplaySize = ImVec2((float)w, (float)h); | ||||
|     if (w > 0 && h > 0) | ||||
|         io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h); | ||||
| 
 | ||||
|     // Setup time step
 | ||||
|     // (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
 | ||||
|     double current_time = glfwGetTime(); | ||||
|     if (current_time <= bd->Time) | ||||
|         current_time = bd->Time + 0.00001f; | ||||
|     io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); | ||||
|     bd->Time = current_time; | ||||
| 
 | ||||
|     ImGui_ImplGlfw_UpdateMouseData(); | ||||
|     ImGui_ImplGlfw_UpdateMouseCursor(); | ||||
| 
 | ||||
|     // Update game controllers (if enabled and available)
 | ||||
|     ImGui_ImplGlfw_UpdateGamepads(); | ||||
| } | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| #if defined(__clang__) | ||||
| #pragma clang diagnostic pop | ||||
| #endif | ||||
| 
 | ||||
| #endif // #ifndef IMGUI_DISABLE
 | ||||
|  | @ -0,0 +1,53 @@ | |||
| // dear imgui: Platform Backend for GLFW
 | ||||
| // This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
 | ||||
| // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
 | ||||
| 
 | ||||
| // Implemented features:
 | ||||
| //  [X] Platform: Clipboard support.
 | ||||
| //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
 | ||||
| //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
 | ||||
| //  [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 | ||||
| //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
 | ||||
| 
 | ||||
| // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 | ||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 | ||||
| // Learn about Dear ImGui:
 | ||||
| // - FAQ                  https://dearimgui.com/faq
 | ||||
| // - Getting Started      https://dearimgui.com/getting-started
 | ||||
| // - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
 | ||||
| // - Introduction, links and more at the top of imgui.cpp
 | ||||
| 
 | ||||
| #pragma once | ||||
| #include "imgui.h"      // IMGUI_IMPL_API | ||||
| #ifndef IMGUI_DISABLE | ||||
| 
 | ||||
| struct GLFWwindow; | ||||
| struct GLFWmonitor; | ||||
| 
 | ||||
| IMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); | ||||
| IMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); | ||||
| IMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_Shutdown(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_NewFrame(); | ||||
| 
 | ||||
| // GLFW callbacks install
 | ||||
| // - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any.
 | ||||
| // - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks.
 | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window); | ||||
| 
 | ||||
| // GFLW callbacks options:
 | ||||
| // - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user)
 | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows); | ||||
| 
 | ||||
| // GLFW callbacks (individual callbacks to call yourself if you didn't install callbacks)
 | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused);        // Since 1.84
 | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered);        // Since 1.84
 | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y);   // Since 1.87
 | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event); | ||||
| 
 | ||||
| #endif // #ifndef IMGUI_DISABLE
 | ||||
|  | @ -0,0 +1,302 @@ | |||
| // dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline)
 | ||||
| // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
 | ||||
| 
 | ||||
| // Implemented features:
 | ||||
| //  [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
 | ||||
| 
 | ||||
| // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 | ||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 | ||||
| // Learn about Dear ImGui:
 | ||||
| // - FAQ                  https://dearimgui.com/faq
 | ||||
| // - Getting Started      https://dearimgui.com/getting-started
 | ||||
| // - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
 | ||||
| // - Introduction, links and more at the top of imgui.cpp
 | ||||
| 
 | ||||
| // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
 | ||||
| // **Prefer using the code in imgui_impl_opengl3.cpp**
 | ||||
| // This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
 | ||||
| // If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
 | ||||
| // complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
 | ||||
| // confuse your GPU driver.
 | ||||
| // The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
 | ||||
| 
 | ||||
| // CHANGELOG
 | ||||
| // (minor and older changes stripped away, please see git history for details)
 | ||||
| //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 | ||||
| //  2021-12-08: OpenGL: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
 | ||||
| //  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
 | ||||
| //  2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
 | ||||
| //  2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications.
 | ||||
| //  2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications.
 | ||||
| //  2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
 | ||||
| //  2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
 | ||||
| //  2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
 | ||||
| //  2018-08-03: OpenGL: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications.
 | ||||
| //  2018-06-08: Misc: Extracted imgui_impl_opengl2.cpp/.h away from the old combined GLFW/SDL+OpenGL2 examples.
 | ||||
| //  2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
 | ||||
| //  2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplOpenGL2_RenderDrawData() in the .h file so you can call it yourself.
 | ||||
| //  2017-09-01: OpenGL: Save and restore current polygon mode.
 | ||||
| //  2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal).
 | ||||
| //  2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
 | ||||
| 
 | ||||
| #include "imgui.h" | ||||
| #ifndef IMGUI_DISABLE | ||||
| #include "imgui_impl_opengl2.h" | ||||
| #include <stdint.h>     // intptr_t
 | ||||
| 
 | ||||
| // Clang/GCC warnings with -Weverything
 | ||||
| #if defined(__clang__) | ||||
| #pragma clang diagnostic push | ||||
| #pragma clang diagnostic ignored "-Wunused-macros"                      // warning: macro is not used
 | ||||
| #pragma clang diagnostic ignored "-Wnonportable-system-include-path" | ||||
| #endif | ||||
| 
 | ||||
| // Include OpenGL header (without an OpenGL loader) requires a bit of fiddling
 | ||||
| #if defined(_WIN32) && !defined(APIENTRY) | ||||
| #define APIENTRY __stdcall                  // It is customary to use APIENTRY for OpenGL function pointer declarations on all platforms.  Additionally, the Windows OpenGL header needs APIENTRY.
 | ||||
| #endif | ||||
| #if defined(_WIN32) && !defined(WINGDIAPI) | ||||
| #define WINGDIAPI __declspec(dllimport)     // Some Windows OpenGL headers need this
 | ||||
| #endif | ||||
| #if defined(__APPLE__) | ||||
| #define GL_SILENCE_DEPRECATION | ||||
| #include <OpenGL/gl.h> | ||||
| #else | ||||
| #include <GL/gl.h> | ||||
| #endif | ||||
| 
 | ||||
| struct ImGui_ImplOpenGL2_Data | ||||
| { | ||||
|     GLuint       FontTexture; | ||||
| 
 | ||||
|     ImGui_ImplOpenGL2_Data() { memset((void*)this, 0, sizeof(*this)); } | ||||
| }; | ||||
| 
 | ||||
| // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
 | ||||
| // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
 | ||||
| static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData() | ||||
| { | ||||
|     return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; | ||||
| } | ||||
| 
 | ||||
| // Functions
 | ||||
| bool    ImGui_ImplOpenGL2_Init() | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); | ||||
| 
 | ||||
|     // Setup backend capabilities flags
 | ||||
|     ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)(); | ||||
|     io.BackendRendererUserData = (void*)bd; | ||||
|     io.BackendRendererName = "imgui_impl_opengl2"; | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void    ImGui_ImplOpenGL2_Shutdown() | ||||
| { | ||||
|     ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); | ||||
|     IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
| 
 | ||||
|     ImGui_ImplOpenGL2_DestroyDeviceObjects(); | ||||
|     io.BackendRendererName = nullptr; | ||||
|     io.BackendRendererUserData = nullptr; | ||||
|     IM_DELETE(bd); | ||||
| } | ||||
| 
 | ||||
| void    ImGui_ImplOpenGL2_NewFrame() | ||||
| { | ||||
|     ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); | ||||
|     IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplOpenGL2_Init()?"); | ||||
| 
 | ||||
|     if (!bd->FontTexture) | ||||
|         ImGui_ImplOpenGL2_CreateDeviceObjects(); | ||||
| } | ||||
| 
 | ||||
| static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height) | ||||
| { | ||||
|     // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
 | ||||
|     glEnable(GL_BLEND); | ||||
|     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
|     //glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // In order to composite our output buffer we need to preserve alpha
 | ||||
|     glDisable(GL_CULL_FACE); | ||||
|     glDisable(GL_DEPTH_TEST); | ||||
|     glDisable(GL_STENCIL_TEST); | ||||
|     glDisable(GL_LIGHTING); | ||||
|     glDisable(GL_COLOR_MATERIAL); | ||||
|     glEnable(GL_SCISSOR_TEST); | ||||
|     glEnableClientState(GL_VERTEX_ARRAY); | ||||
|     glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||||
|     glEnableClientState(GL_COLOR_ARRAY); | ||||
|     glDisableClientState(GL_NORMAL_ARRAY); | ||||
|     glEnable(GL_TEXTURE_2D); | ||||
|     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
|     glShadeModel(GL_SMOOTH); | ||||
|     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | ||||
| 
 | ||||
|     // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
 | ||||
|     // you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
 | ||||
|     // (DO NOT MODIFY THIS FILE! Add the code in your calling function)
 | ||||
|     //   GLint last_program;
 | ||||
|     //   glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
 | ||||
|     //   glUseProgram(0);
 | ||||
|     //   ImGui_ImplOpenGL2_RenderDrawData(...);
 | ||||
|     //   glUseProgram(last_program)
 | ||||
|     // There are potentially many more states you could need to clear/setup that we can't access from default headers.
 | ||||
|     // e.g. glBindBuffer(GL_ARRAY_BUFFER, 0), glDisable(GL_TEXTURE_CUBE_MAP).
 | ||||
| 
 | ||||
|     // Setup viewport, orthographic projection matrix
 | ||||
|     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
 | ||||
|     glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); | ||||
|     glMatrixMode(GL_PROJECTION); | ||||
|     glPushMatrix(); | ||||
|     glLoadIdentity(); | ||||
|     glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f); | ||||
|     glMatrixMode(GL_MODELVIEW); | ||||
|     glPushMatrix(); | ||||
|     glLoadIdentity(); | ||||
| } | ||||
| 
 | ||||
| // OpenGL2 Render function.
 | ||||
| // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
 | ||||
| // This is in order to be able to run within an OpenGL engine that doesn't do so.
 | ||||
| void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) | ||||
| { | ||||
|     // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
 | ||||
|     int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); | ||||
|     int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); | ||||
|     if (fb_width == 0 || fb_height == 0) | ||||
|         return; | ||||
| 
 | ||||
|     // Backup GL state
 | ||||
|     GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); | ||||
|     GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); | ||||
|     GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); | ||||
|     GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); | ||||
|     GLint last_shade_model; glGetIntegerv(GL_SHADE_MODEL, &last_shade_model); | ||||
|     GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode); | ||||
|     glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); | ||||
| 
 | ||||
|     // Setup desired GL state
 | ||||
|     ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height); | ||||
| 
 | ||||
|     // Will project scissor/clipping rectangles into framebuffer space
 | ||||
|     ImVec2 clip_off = draw_data->DisplayPos;         // (0,0) unless using multi-viewports
 | ||||
|     ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
 | ||||
| 
 | ||||
|     // Render command lists
 | ||||
|     for (int n = 0; n < draw_data->CmdListsCount; n++) | ||||
|     { | ||||
|         const ImDrawList* cmd_list = draw_data->CmdLists[n]; | ||||
|         const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; | ||||
|         const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; | ||||
|         glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos))); | ||||
|         glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv))); | ||||
|         glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col))); | ||||
| 
 | ||||
|         for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) | ||||
|         { | ||||
|             const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; | ||||
|             if (pcmd->UserCallback) | ||||
|             { | ||||
|                 // User callback, registered via ImDrawList::AddCallback()
 | ||||
|                 // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
 | ||||
|                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) | ||||
|                     ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height); | ||||
|                 else | ||||
|                     pcmd->UserCallback(cmd_list, pcmd); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // Project scissor/clipping rectangles into framebuffer space
 | ||||
|                 ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); | ||||
|                 ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); | ||||
|                 if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) | ||||
|                     continue; | ||||
| 
 | ||||
|                 // Apply scissor/clipping rectangle (Y is inverted in OpenGL)
 | ||||
|                 glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)); | ||||
| 
 | ||||
|                 // Bind texture, Draw
 | ||||
|                 glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()); | ||||
|                 glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Restore modified GL state
 | ||||
|     glDisableClientState(GL_COLOR_ARRAY); | ||||
|     glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||||
|     glDisableClientState(GL_VERTEX_ARRAY); | ||||
|     glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture); | ||||
|     glMatrixMode(GL_MODELVIEW); | ||||
|     glPopMatrix(); | ||||
|     glMatrixMode(GL_PROJECTION); | ||||
|     glPopMatrix(); | ||||
|     glPopAttrib(); | ||||
|     glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); | ||||
|     glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); | ||||
|     glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); | ||||
|     glShadeModel(last_shade_model); | ||||
|     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode); | ||||
| } | ||||
| 
 | ||||
| bool ImGui_ImplOpenGL2_CreateFontsTexture() | ||||
| { | ||||
|     // Build texture atlas
 | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); | ||||
|     unsigned char* pixels; | ||||
|     int width, height; | ||||
|     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);   // Load as RGBA 32-bit (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.
 | ||||
| 
 | ||||
|     // Upload texture to graphics system
 | ||||
|     // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
 | ||||
|     GLint last_texture; | ||||
|     glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); | ||||
|     glGenTextures(1, &bd->FontTexture); | ||||
|     glBindTexture(GL_TEXTURE_2D, bd->FontTexture); | ||||
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
|     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | ||||
|     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); | ||||
| 
 | ||||
|     // Store our identifier
 | ||||
|     io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture); | ||||
| 
 | ||||
|     // Restore state
 | ||||
|     glBindTexture(GL_TEXTURE_2D, last_texture); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void ImGui_ImplOpenGL2_DestroyFontsTexture() | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); | ||||
|     if (bd->FontTexture) | ||||
|     { | ||||
|         glDeleteTextures(1, &bd->FontTexture); | ||||
|         io.Fonts->SetTexID(0); | ||||
|         bd->FontTexture = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool    ImGui_ImplOpenGL2_CreateDeviceObjects() | ||||
| { | ||||
|     return ImGui_ImplOpenGL2_CreateFontsTexture(); | ||||
| } | ||||
| 
 | ||||
| void    ImGui_ImplOpenGL2_DestroyDeviceObjects() | ||||
| { | ||||
|     ImGui_ImplOpenGL2_DestroyFontsTexture(); | ||||
| } | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| #if defined(__clang__) | ||||
| #pragma clang diagnostic pop | ||||
| #endif | ||||
| 
 | ||||
| #endif // #ifndef IMGUI_DISABLE
 | ||||
|  | @ -0,0 +1,38 @@ | |||
| // dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline)
 | ||||
| // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
 | ||||
| 
 | ||||
| // Implemented features:
 | ||||
| //  [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
 | ||||
| 
 | ||||
| // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 | ||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 | ||||
| // Learn about Dear ImGui:
 | ||||
| // - FAQ                  https://dearimgui.com/faq
 | ||||
| // - Getting Started      https://dearimgui.com/getting-started
 | ||||
| // - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
 | ||||
| // - Introduction, links and more at the top of imgui.cpp
 | ||||
| 
 | ||||
| // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
 | ||||
| // **Prefer using the code in imgui_impl_opengl3.cpp**
 | ||||
| // This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
 | ||||
| // If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
 | ||||
| // complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
 | ||||
| // confuse your GPU driver.
 | ||||
| // The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
 | ||||
| 
 | ||||
| #pragma once | ||||
| #include "imgui.h"      // IMGUI_IMPL_API | ||||
| #ifndef IMGUI_DISABLE | ||||
| 
 | ||||
| IMGUI_IMPL_API bool     ImGui_ImplOpenGL2_Init(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplOpenGL2_Shutdown(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplOpenGL2_NewFrame(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data); | ||||
| 
 | ||||
| // Called by Init/NewFrame/Shutdown
 | ||||
| IMGUI_IMPL_API bool     ImGui_ImplOpenGL2_CreateFontsTexture(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplOpenGL2_DestroyFontsTexture(); | ||||
| IMGUI_IMPL_API bool     ImGui_ImplOpenGL2_CreateDeviceObjects(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplOpenGL2_DestroyDeviceObjects(); | ||||
| 
 | ||||
| #endif // #ifndef IMGUI_DISABLE
 | ||||
							
								
								
									
										45
									
								
								kge.cc
								
								
								
								
							
							
						
						
									
										45
									
								
								kge.cc
								
								
								
								
							|  | @ -1,10 +1,53 @@ | |||
| //
 | ||||
| // Created by kyle on 2023-10-04.
 | ||||
| //
 | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include "Platform.h" | ||||
| #include "GUI.h" | ||||
| 
 | ||||
| static void | ||||
| glfw_error_callback(int error, const char *description) | ||||
| { | ||||
| 	cerr << "GLFW error " << error << ": " << description << std::endl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| main(int argc, const char *argv[]) | ||||
| { | ||||
| 	const char *glsl_version = "#version 130"; | ||||
| 	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | ||||
| 	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | ||||
| 
 | ||||
| 	// Setup window
 | ||||
| 	glfwSetErrorCallback(glfw_error_callback); | ||||
| 	if (!glfwInit()) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (window == NULL) | ||||
| 		return 1; | ||||
| 	glfwMakeContextCurrent(window); | ||||
| 	glfwSwapInterval(1); // Enable vsync
 | ||||
| 
 | ||||
| 	bool err = glewInit() != GLEW_OK; | ||||
| 
 | ||||
| 	if (err) | ||||
| 	{ | ||||
| 		std::cerr << "Failed to initialize OpenGL loader!" << std::endl; | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	int screen_width, screen_height; | ||||
| 	glfwGetFramebufferSize(window, &screen_width, &screen_height); | ||||
| 	glViewport(0, 0, screen_width, screen_height); | ||||
| 
 | ||||
| 
 | ||||
| 	IMGUI_CHECKVERSION(); | ||||
| 	ImGui::CreateContext(NULL); | ||||
| 	ImGuiIO	&io = ImGui::GetIO(); | ||||
| 	ImGui_ImplGlfw_InitForOpenGL(window, true); | ||||
| 	ImGui_ImplOpenGL3_Init(glsl_version); | ||||
| 	return 0; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue