diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 83a4b88e4..4c8704787 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -76,6 +76,7 @@ Other Changes: - SliderFloat(): When using keyboard/gamepad and a zero precision format string (e.g. "%.0f"), always step in integer units. (#1866) - ImFontConfig: Added GlyphMinAdvanceX/GlyphMaxAdvanceX settings useful to make a font appears monospaced, particularly useful for icon fonts. (#1869) - ImFontAtlas: Added GetGlyphRangesChineseSimplifiedCommon() helper that returns a list of ~2500 most common Simplified Chinese characters. (#1859) [@JX-Master, @ocornut] + - Examples: OSX: Added imgui_impl_osx.mm binding to be used along with e.g. imgui_impl_opengl2.cpp. (#281, #1870) [@pagghiu, @itamago, @ocornut] - Examples: GLFW: Made it possible to Shutdown/Init the backend again (by reseting the time storage properly). (#1827) [@ice1000] - Misc: Updated stb_textedit from 1.09 + patches to 1.12 + minor patches. - Internals: PushItemFlag() flags are inherited by BeginChild(). diff --git a/examples/.gitignore b/examples/.gitignore index db2859e1d..e3f0f12b1 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -9,13 +9,18 @@ build/* *.vcxproj.user *.o *.obj -*.exe *.pdb *.ilk *.VC.db *.VC.VC.opendb -## Unix executables +## XCode cruft +.DS_Store +project.xcworkspace +xcuserdata/* + +## Executables +*.exe example_glfw_opengl2/example_glfw_opengl2 example_glfw_opengl3/example_glfw_opengl3 example_sdl_opengl2/example_sdl_opengl2 diff --git a/examples/README.txt b/examples/README.txt index 407cceb91..2dce98da6 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -109,6 +109,7 @@ Most the example bindings are split in 2 parts: List of officially maintained Platforms Bindings: imgui_impl_glfw.cpp + imgui_impl_osx.mm imgui_impl_sdl.cpp imgui_impl_win32.cpp @@ -212,10 +213,14 @@ example_sdl_vulkan/ This is quite long and tedious, because: Vulkan. = main.cpp + imgui_impl_sdl.cpp + imgui_impl_vulkan.cpp +example_osx_opengl2/ + OSX Cocoa + OpenGL2. + = main.mm + imgui_impl_osx.mm + imgui_impl_opengl2.cpp + example_apple/ OSX & iOS example + OpenGL2. THIS EXAMPLE HAS NOT BEEN MAINTAINED PROPERLY AND NEEDS A MAINTAINER. - Consider using the example_glfw_opengl3/ instead. + Consider using the example_glfw_opengl3/ or example_osx_opengl2/ example instead. On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. diff --git a/examples/example_apple/.gitignore b/examples/example_apple/.gitignore deleted file mode 100644 index 8feda89d3..000000000 --- a/examples/example_apple/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.DS_Store -imguiex.xcodeproj/project.xcworkspace/ -imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/example_osx_opengl2/example_osx_opengl2.xcodeproj/project.pbxproj b/examples/example_osx_opengl2/example_osx_opengl2.xcodeproj/project.pbxproj new file mode 100644 index 000000000..a325e96da --- /dev/null +++ b/examples/example_osx_opengl2/example_osx_opengl2.xcodeproj/project.pbxproj @@ -0,0 +1,325 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 4080A99820B02D340036BA46 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4080A98A20B02CD90036BA46 /* main.mm */; }; + 4080A9A220B034280036BA46 /* imgui_impl_opengl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */; }; + 4080A9AD20B0343C0036BA46 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A9A620B0343C0036BA46 /* imgui_demo.cpp */; }; + 4080A9AE20B0343C0036BA46 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A9A720B0343C0036BA46 /* imgui.cpp */; }; + 4080A9AF20B0343C0036BA46 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */; }; + 4080A9B020B0347A0036BA46 /* imgui_impl_osx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4080A99F20B034280036BA46 /* imgui_impl_osx.mm */; }; + 4080A9B320B034E40036BA46 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4080A9B220B034E40036BA46 /* Cocoa.framework */; }; + 4080A9B520B034EA0036BA46 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4080A9B420B034EA0036BA46 /* OpenGL.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4080A96920B029B00036BA46 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 4080A96B20B029B00036BA46 /* example_osx_opengl2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = example_osx_opengl2; sourceTree = BUILT_PRODUCTS_DIR; }; + 4080A98A20B02CD90036BA46 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = SOURCE_ROOT; }; + 4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_impl_opengl2.cpp; path = ../imgui_impl_opengl2.cpp; sourceTree = ""; }; + 4080A99F20B034280036BA46 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../imgui_impl_osx.mm; sourceTree = ""; }; + 4080A9A020B034280036BA46 /* imgui_impl_opengl2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_opengl2.h; path = ../imgui_impl_opengl2.h; sourceTree = ""; }; + 4080A9A120B034280036BA46 /* imgui_impl_osx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_osx.h; path = ../imgui_impl_osx.h; sourceTree = ""; }; + 4080A9A420B0343C0036BA46 /* stb_truetype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_truetype.h; path = ../../stb_truetype.h; sourceTree = ""; }; + 4080A9A520B0343C0036BA46 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = ""; }; + 4080A9A620B0343C0036BA46 /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../imgui_demo.cpp; sourceTree = ""; }; + 4080A9A720B0343C0036BA46 /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 4080A9A820B0343C0036BA46 /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 4080A9A920B0343C0036BA46 /* stb_rect_pack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_rect_pack.h; path = ../../stb_rect_pack.h; sourceTree = ""; }; + 4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 4080A9AB20B0343C0036BA46 /* stb_textedit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_textedit.h; path = ../../stb_textedit.h; sourceTree = ""; }; + 4080A9AC20B0343C0036BA46 /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 4080A9B220B034E40036BA46 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 4080A9B420B034EA0036BA46 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4080A96820B029B00036BA46 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4080A9B520B034EA0036BA46 /* OpenGL.framework in Frameworks */, + 4080A9B320B034E40036BA46 /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4080A96220B029B00036BA46 = { + isa = PBXGroup; + children = ( + 4080A9AC20B0343C0036BA46 /* imconfig.h */, + 4080A9A620B0343C0036BA46 /* imgui_demo.cpp */, + 4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */, + 4080A9A520B0343C0036BA46 /* imgui_internal.h */, + 4080A9A720B0343C0036BA46 /* imgui.cpp */, + 4080A9A820B0343C0036BA46 /* imgui.h */, + 4080A9A920B0343C0036BA46 /* stb_rect_pack.h */, + 4080A9AB20B0343C0036BA46 /* stb_textedit.h */, + 4080A9A420B0343C0036BA46 /* stb_truetype.h */, + 4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */, + 4080A9A020B034280036BA46 /* imgui_impl_opengl2.h */, + 4080A9A120B034280036BA46 /* imgui_impl_osx.h */, + 4080A99F20B034280036BA46 /* imgui_impl_osx.mm */, + 4080A98A20B02CD90036BA46 /* main.mm */, + 4080A96C20B029B00036BA46 /* Products */, + 4080A9B120B034E40036BA46 /* Frameworks */, + ); + sourceTree = ""; + }; + 4080A96C20B029B00036BA46 /* Products */ = { + isa = PBXGroup; + children = ( + 4080A96B20B029B00036BA46 /* example_osx_opengl2 */, + ); + name = Products; + sourceTree = ""; + }; + 4080A9B120B034E40036BA46 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4080A9B420B034EA0036BA46 /* OpenGL.framework */, + 4080A9B220B034E40036BA46 /* Cocoa.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4080A96A20B029B00036BA46 /* example_osx_opengl2 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4080A97220B029B00036BA46 /* Build configuration list for PBXNativeTarget "example_osx_opengl2" */; + buildPhases = ( + 4080A96720B029B00036BA46 /* Sources */, + 4080A96820B029B00036BA46 /* Frameworks */, + 4080A96920B029B00036BA46 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = example_osx_opengl2; + productName = example_osx_opengl2; + productReference = 4080A96B20B029B00036BA46 /* example_osx_opengl2 */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4080A96320B029B00036BA46 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = ImGui; + TargetAttributes = { + 4080A96A20B029B00036BA46 = { + CreatedOnToolsVersion = 9.3.1; + }; + }; + }; + buildConfigurationList = 4080A96620B029B00036BA46 /* Build configuration list for PBXProject "example_osx_opengl2" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4080A96220B029B00036BA46; + productRefGroup = 4080A96C20B029B00036BA46 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4080A96A20B029B00036BA46 /* example_osx_opengl2 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4080A96720B029B00036BA46 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4080A99820B02D340036BA46 /* main.mm in Sources */, + 4080A9AD20B0343C0036BA46 /* imgui_demo.cpp in Sources */, + 4080A9AF20B0343C0036BA46 /* imgui_draw.cpp in Sources */, + 4080A9A220B034280036BA46 /* imgui_impl_opengl2.cpp in Sources */, + 4080A9B020B0347A0036BA46 /* imgui_impl_osx.mm in Sources */, + 4080A9AE20B0343C0036BA46 /* imgui.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4080A97020B029B00036BA46 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 4080A97120B029B00036BA46 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 4080A97320B029B00036BA46 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + SYSTEM_HEADER_SEARCH_PATHS = ../libs/gl3w; + USER_HEADER_SEARCH_PATHS = ../..; + }; + name = Debug; + }; + 4080A97420B029B00036BA46 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + SYSTEM_HEADER_SEARCH_PATHS = ../libs/gl3w; + USER_HEADER_SEARCH_PATHS = ../..; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4080A96620B029B00036BA46 /* Build configuration list for PBXProject "example_osx_opengl2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4080A97020B029B00036BA46 /* Debug */, + 4080A97120B029B00036BA46 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4080A97220B029B00036BA46 /* Build configuration list for PBXNativeTarget "example_osx_opengl2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4080A97320B029B00036BA46 /* Debug */, + 4080A97420B029B00036BA46 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4080A96320B029B00036BA46 /* Project object */; +} diff --git a/examples/example_osx_opengl2/main.mm b/examples/example_osx_opengl2/main.mm new file mode 100644 index 000000000..c4b4a968c --- /dev/null +++ b/examples/example_osx_opengl2/main.mm @@ -0,0 +1,280 @@ +// ImGui - standalone example application for OSX + OpenGL2, using legacy fixed pipeline +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. + +#include "imgui.h" +#include "../imgui_impl_osx.h" +#include "../imgui_impl_opengl2.h" +#include +#import +#import +#import + +//----------------------------------------------------------------------------------- +// ImGuiExampleView +//----------------------------------------------------------------------------------- + +@interface ImGuiExampleView : NSOpenGLView +{ + NSTimer* animationTimer; +} +@end + +@implementation ImGuiExampleView + +-(void)animationTimerFired:(NSTimer*)timer +{ + [self setNeedsDisplay:YES]; +} + +-(void)prepareOpenGL +{ + [super prepareOpenGL]; + +#ifndef DEBUG + GLint swapInterval = 1; + [[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; + if (swapInterval == 0) + NSLog(@"Error: Cannot set swap interval."); +#endif +} + +-(void)updateAndDrawDemoView +{ + ImGui_ImplOpenGL2_NewFrame(); + ImGui_ImplOSX_NewFrame(self); + + // Global data for the demo + static bool show_demo_window = true; + static bool show_another_window = false; + static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". + { + static float f = 0.0f; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + } + + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! + if (show_demo_window) + { + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! + ImGui::ShowDemoWindow(&show_demo_window); + } + + // Rendering + ImGui::Render(); + [[self openGLContext] makeCurrentContext]; + + ImGuiIO& io = ImGui::GetIO(); + GLsizei width = (GLsizei)(io.DisplaySize.x * io.DisplayFramebufferScale.x); + GLsizei height = (GLsizei)(io.DisplaySize.y * io.DisplayFramebufferScale.y); + glViewport(0, 0, width, height); + + glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); + glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); + + // Present + [[self openGLContext] flushBuffer]; + + if (!animationTimer) + animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.017 target:self selector:@selector(animationTimerFired:) userInfo:nil repeats:YES]; +} + +-(void)reshape +{ + [[self openGLContext] update]; + [self updateAndDrawDemoView]; +} + +-(void)drawRect:(NSRect)bounds +{ + [self updateAndDrawDemoView]; +} + +-(BOOL)acceptsFirstResponder +{ + return (YES); +} + +-(BOOL)becomeFirstResponder +{ + return (YES); +} + +-(BOOL)resignFirstResponder +{ + return (YES); +} + +// Flip coordinate system upside down on Y +-(BOOL)isFlipped +{ + return (YES); +} + +-(void)dealloc +{ + animationTimer = nil; +} + +// Forward Mouse/Keyboard events to dear imgui OSX back-end. It returns true when imgui is expecting to use the event. +-(void)keyUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event); } +-(void)keyDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event); } +-(void)flagsChanged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event); } +-(void)mouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event); } +-(void)mouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event); } +-(void)scrollWheel:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event); } + +@end + +//----------------------------------------------------------------------------------- +// ImGuiExampleAppDelegate +//----------------------------------------------------------------------------------- + +@interface ImGuiExampleAppDelegate : NSObject +@property (nonatomic, readonly) NSWindow* window; +@end + +@implementation ImGuiExampleAppDelegate +@synthesize window = _window; + +-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication +{ + return YES; +} + +-(NSWindow*)window +{ + if (_window != nil) + return (_window); + + NSRect viewRect = NSMakeRect(100.0, 100.0, 100.0 + 1280.0, 100 + 720.0); + + _window = [[NSWindow alloc] initWithContentRect:viewRect styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable|NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:YES]; + [_window setTitle:@"ImGui OSX+OpenGL2 Example"]; + [_window setOpaque:YES]; + [_window makeKeyAndOrderFront:NSApp]; + + return (_window); +} + +-(void)setupMenu +{ + NSMenu* mainMenuBar = [[NSMenu alloc] init]; + NSMenu* appMenu; + NSMenuItem* menuItem; + + appMenu = [[NSMenu alloc] initWithTitle:@"ImGui OSX+OpenGL2 Example"]; + menuItem = [appMenu addItemWithTitle:@"Quit ImGui OSX+OpenGL2 Example" action:@selector(terminate:) keyEquivalent:@"q"]; + [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; + + menuItem = [[NSMenuItem alloc] init]; + [menuItem setSubmenu:appMenu]; + + [mainMenuBar addItem:menuItem]; + + appMenu = nil; + [NSApp setMainMenu:mainMenuBar]; +} + +-(void)dealloc +{ + _window = nil; +} + +-(void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + // Make the application a foreground application (else it won't receive keyboard events) + ProcessSerialNumber psn = {0, kCurrentProcess}; + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + + // Menu + [self setupMenu]; + + NSOpenGLPixelFormatAttribute attrs[] = + { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFADepthSize, 32, + 0 + }; + + NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; + ImGuiExampleView* view = [[ImGuiExampleView alloc] initWithFrame:self.window.frame pixelFormat:format]; + format = nil; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) + [view setWantsBestResolutionOpenGLSurface:YES]; +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + [self.window setContentView:view]; + + if ([view openGLContext] == nil) + NSLog(@"No OpenGL Context!"); + + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + + ImGui_ImplOSX_Init(); + ImGui_ImplOpenGL2_Init(); + + // Setup style + ImGui::GetStyle().WindowRounding = 0.0f; + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'misc/fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); +} + +@end + +int main(int argc, const char* argv[]) +{ + @autoreleasepool + { + NSApp = [NSApplication sharedApplication]; + ImGuiExampleAppDelegate* delegate = [[ImGuiExampleAppDelegate alloc] init]; + [[NSApplication sharedApplication] setDelegate:delegate]; + [NSApp run]; + } + return NSApplicationMain(argc, argv); +} diff --git a/examples/imgui_impl_osx.h b/examples/imgui_impl_osx.h new file mode 100644 index 000000000..0626371dc --- /dev/null +++ b/examples/imgui_impl_osx.h @@ -0,0 +1,11 @@ +// ImGui Platform Binding for: OSX / Cocoa +// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan..) + +@class NSEvent; +@class NSOpenGLView; + +// FIXME-OSX: Try replacing with NSView +IMGUI_API bool ImGui_ImplOSX_Init(); +IMGUI_API void ImGui_ImplOSX_Shutdown(); +IMGUI_API void ImGui_ImplOSX_NewFrame(NSOpenGLView* view); +IMGUI_API bool ImGui_ImplOSX_HandleEvent(NSEvent* event); diff --git a/examples/imgui_impl_osx.mm b/examples/imgui_impl_osx.mm new file mode 100644 index 000000000..19018e693 --- /dev/null +++ b/examples/imgui_impl_osx.mm @@ -0,0 +1,236 @@ +// ImGui Platform Binding for: OSX / Cocoa +// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan..) + +// FIXME-OSX: Keyboard mapping is weird. +// FIXME-OSX: Mouse cursor shape support (see https://github.com/glfw/glfw/issues/427) +// FIXME-OSX: Test renderer backend combination, e.g. OpenGL3 + +#include "imgui.h" +#include "imgui_impl_osx.h" +#import + +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-XX-XX: Initial version. + +// Data +static clock_t g_Time = 0; + +// Functions +bool ImGui_ImplOSX_Init() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup back-end capabilities flags + //io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + //io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + //io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional) + //io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy) + + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_Tab] = 9; + io.KeyMap[ImGuiKey_LeftArrow] = ImGuiKey_LeftArrow; + io.KeyMap[ImGuiKey_RightArrow] = ImGuiKey_RightArrow; + io.KeyMap[ImGuiKey_UpArrow] = ImGuiKey_UpArrow; + io.KeyMap[ImGuiKey_DownArrow] = ImGuiKey_DownArrow; + io.KeyMap[ImGuiKey_PageUp] = ImGuiKey_PageUp; + io.KeyMap[ImGuiKey_PageDown] = ImGuiKey_PageDown; + io.KeyMap[ImGuiKey_Home] = ImGuiKey_Home; + io.KeyMap[ImGuiKey_End] = ImGuiKey_End; + io.KeyMap[ImGuiKey_Insert] = ImGuiKey_Insert; + io.KeyMap[ImGuiKey_Delete] = ImGuiKey_Delete; + io.KeyMap[ImGuiKey_Backspace] = 127; + io.KeyMap[ImGuiKey_Space] = 32; + io.KeyMap[ImGuiKey_Enter] = 13; + io.KeyMap[ImGuiKey_Escape] = 27; + io.KeyMap[ImGuiKey_A] = 'a'; + io.KeyMap[ImGuiKey_C] = 'c'; + io.KeyMap[ImGuiKey_V] = 'v'; + io.KeyMap[ImGuiKey_X] = 'x'; + io.KeyMap[ImGuiKey_Y] = 'y'; + io.KeyMap[ImGuiKey_Z] = 'z'; + + // Time elapsed since last frame, in seconds + // (in this sample app we'll override this every frame because our time step is variable) + io.DeltaTime = 1.0f/60.0f; + + return true; +} + +void ImGui_ImplOSX_Shutdown() +{ +} + +void ImGui_ImplOSX_NewFrame(NSOpenGLView* view) +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size + const float dpi = [view.window backingScaleFactor]; + io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bounds.size.height); + io.DisplayFramebufferScale = ImVec2(dpi, dpi); + + // Setup time step + if (g_Time == 0) + g_Time = clock(); + clock_t current_time = clock(); + io.DeltaTime = (double)(current_time - g_Time) / CLOCKS_PER_SEC; + g_Time = current_time; + + NSWindow* main_window = [view window]; + NSPoint mouse_pos = [main_window mouseLocationOutsideOfEventStream]; + mouse_pos = [view convertPoint:mouse_pos fromView:nil]; + io.MousePos = ImVec2(mouse_pos.x, mouse_pos.y - 1); + + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. + ImGui::NewFrame(); +} + +// FIXME-OSX: Store in io.KeysDown[] +static bool mapKeymap(int* keymap) +{ + if (*keymap == NSUpArrowFunctionKey) + *keymap = ImGuiKey_LeftArrow; + else if (*keymap == NSDownArrowFunctionKey) + *keymap = ImGuiKey_DownArrow; + else if (*keymap == NSLeftArrowFunctionKey) + *keymap = ImGuiKey_LeftArrow; + else if (*keymap == NSRightArrowFunctionKey) + *keymap = ImGuiKey_RightArrow; + else if (*keymap == NSHomeFunctionKey) + *keymap = ImGuiKey_Home; + else if (*keymap == NSEndFunctionKey) + *keymap = ImGuiKey_End; + else if (*keymap == NSDeleteFunctionKey) + *keymap = ImGuiKey_Delete; + else if (*keymap == 25) // SHIFT + TAB + *keymap = 9; // TAB + else + return true; + + return false; +} + +static void ResetKeys() +{ + // FIXME-OSX: Mapping + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[io.KeyMap[ImGuiKey_A]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_C]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_V]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_X]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_Y]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_Z]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_LeftArrow]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_RightArrow]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_Tab]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_UpArrow]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_DownArrow]] = false; + io.KeysDown[io.KeyMap[ImGuiKey_Tab]] = false; +} + +bool ImGui_ImplOSX_HandleEvent(NSEvent* event) +{ + ImGuiIO& io = ImGui::GetIO(); + + if (event.type == NSEventTypeLeftMouseDown) + { + int button = (int)[event buttonNumber]; + if (button >= 0 && button < IM_ARRAYSIZE(io.MouseDown)) + io.MouseDown[button] = true; + return io.WantCaptureMouse; + } + + if (event.type == NSEventTypeLeftMouseUp) + { + int button = (int)[event buttonNumber]; + if (button >= 0 && button < IM_ARRAYSIZE(io.MouseDown)) + io.MouseDown[button] = false; + return io.WantCaptureMouse; + } + + if (event.type == NSEventTypeScrollWheel) + { + double wheel_dx = 0.0; + double wheel_dy = 0.0; + + #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) + { + wheel_dx = [event scrollingDeltaX]; + wheel_dy = [event scrollingDeltaY]; + if ([event hasPreciseScrollingDeltas]) + { + wheel_dx *= 0.1; + wheel_dy *= 0.1; + } + } + else + #endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ + { + wheel_dx = [event deltaX]; + wheel_dy = [event deltaY]; + } + + if (fabs(wheel_dx) > 0.0) + io.MouseWheelH += wheel_dx * 0.1f; + if (fabs(wheel_dy) > 0.0) + io.MouseWheel += wheel_dy * 0.1f; + return io.WantCaptureMouse; + } + + if (event.type == NSEventTypeKeyDown) + { + // FIXME-OSX: Try to store native NS keys in KeyDown[] + NSString* str = [event characters]; + int len = (int)[str length]; + for (int i = 0; i < len; i++) + { + int keymap = [str characterAtIndex:i]; + if (mapKeymap(&keymap) && !io.KeyCtrl) + io.AddInputCharacter(keymap); + if (keymap < 512) + { + // We must reset in case we're pressing a sequence of special keys while keeping the command pressed + if (io.KeyCtrl) + ResetKeys(); + io.KeysDown[keymap] = true; + } + } + return io.WantCaptureKeyboard; + } + + if (event.type == NSEventTypeKeyUp) + { + NSString* str = [event characters]; + int len = (int)[str length]; + for (int i = 0; i < len; i++) + { + int keymap = [str characterAtIndex:i]; + mapKeymap(&keymap); + if (keymap < 512) + io.KeysDown[keymap] = false; + } + return io.WantCaptureKeyboard; + } + + if (event.type == NSEventTypeFlagsChanged) + { + unsigned int flags; + flags = [event modifierFlags] & NSDeviceIndependentModifierFlagsMask; + ImGuiIO& io = ImGui::GetIO(); + bool wasKeyShift= io.KeyShift; + bool wasKeyCtrl = io.KeyCtrl; + io.KeyShift = flags & NSShiftKeyMask; + io.KeyCtrl = flags & NSCommandKeyMask; + bool keyShiftReleased = wasKeyShift && !io.KeyShift; + bool keyCtrlReleased = wasKeyCtrl && !io.KeyCtrl; + + // We must reset them as we will not receive any keyUp event if they where pressed during shift or command + if (keyShiftReleased || keyCtrlReleased) + ResetKeys(); + return io.WantCaptureKeyboard; + } + + return false; +}