diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d2482ff1..aa7af662 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -47,6 +47,10 @@ Other Changes: - Misc: Added ImGuiMouseCursor_Hand cursor enum + corresponding software cursor. (#1913, 1914) [@aiekick, @ocornut] - Misc: Tweaked software mouse cursor offset to match the offset of the corresponding Windows 10 cursors. - Fixed a include build issue for Cygwin in non-POSIX (Win32) mode. (#1917, #1319, #276) + - Examples: Metal: Added Metal rendering backend. (#1929, #1873) [@warrenm] + - Examples: OSX: Added early raw OSX platform backend. (#1873) [@pagghiu, @itamago, @ocornut] + - Examples: Added mac OSX & iOS + Metal example in example_apple_metal/. (#1929, #1873) [@warrenm] + - Examples: Added mac OSX + OpenGL2 example in example_apple_opengl2/. (#1873) - Examples: Win32, Glfw, SDL: Added support for the ImGuiMouseCursor_Hand cursor. @@ -99,6 +103,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] - Examples: Win32: Fixed handling of mouse wheel messages to support sub-unit scrolling messages (typically sent by track-pads). (#1874) [@zx64] - Examples: SDL+Vulkan: Added SDL+Vulkan example. diff --git a/README.md b/README.md index 953d5ad6..2abaf031 100644 --- a/README.md +++ b/README.md @@ -125,10 +125,9 @@ Languages: (third-party bindings) - Swift [swift-imgui](https://github.com/mnmly/Swift-imgui) Frameworks: -- Renderers: DirectX 9, DirectX 10, DirectX 11, DirectX 12, OpenGL2, OpenGL3+, Vulkan: [examples/](https://github.com/ocornut/imgui/tree/master/examples) -- Platform: GLFW, SDL, Win32, Freeglut: [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- Renderers: DirectX 9, DirectX 10, DirectX 11, DirectX 12, Metal, OpenGL2, OpenGL3+, Vulkan: [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- Platform: GLFW, SDL, Win32, OSX, Freeglut: [examples/](https://github.com/ocornut/imgui/tree/master/examples) - Framework: Allegro 5, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples) -- Unmerged Branch: OSX platform without GLFW/SDL: [#1873](https://github.com/ocornut/imgui/tree/osx) - Unmerged PR: SDL2 + OpenGLES + Emscripten: [#336](https://github.com/ocornut/imgui/pull/336) - Unmerged PR: Native Win32 and OSX: [#281](https://github.com/ocornut/imgui/pull/281) - Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421) @@ -170,6 +169,7 @@ User screenshots:
[Gallery Part 4](https://github.com/ocornut/imgui/issues/973) (Jan 2017 to Aug 2017)
[Gallery Part 5](https://github.com/ocornut/imgui/issues/1269) (Aug 2017 to Feb 2018)
[Gallery Part 6](https://github.com/ocornut/imgui/issues/1607) (Feb 2018 onward) +
[Gallery Part 6](https://github.com/ocornut/imgui/issues/1902) (June 2018 onward)
Also see the [Mega screenshots](https://github.com/ocornut/imgui/issues/1273) for an idea of the available features. Various tools diff --git a/examples/README.txt b/examples/README.txt index 405768ce..766729d7 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -103,6 +103,7 @@ Most the example bindings are split in 2 parts: List of Platforms Bindings in this repository: imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/ + imgui_impl_osx.mm ; macOS native API imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org imgui_impl_win32.cpp ; Windows native API (Windows) imgui_impl_freeglut.cpp ; FreeGLUT (if you really miss the 90's) @@ -112,7 +113,8 @@ List of Renderer Bindings in this repository: imgui_impl_dx9.cpp ; DirectX9 imgui_impl_dx10.cpp ; DirectX10 imgui_impl_dx11.cpp ; DirectX11 - imgui_impl_dx12.cpp ; DirectX12 + imgui_impl_dx12.cpp ; DirectX12 + imgui_impl_metal.mm ; Metal (with ObjC) imgui_impl_opengl2.cpp ; OpenGL2 (legacy, fixed pipeline <- don't use with modern OpenGL context) imgui_impl_opengl3.cpp ; OpenGL3 (modern programmable pipeline) imgui_impl_vulkan.cpp ; Vulkan @@ -143,6 +145,7 @@ Building: - Makefiles for Linux/OSX - Batch files for Visual Studio 2008+ - A .sln project file for Visual Studio 2010+ + - Xcode project files for the Apple examples Please let me know if they don't work with your setup! You can probably just import the imgui_impl_xxx.cpp/.h files into your own codebase or compile those directly with a command-line compiler. @@ -207,10 +210,19 @@ example_sdl_vulkan/ This is quite long and tedious, because: Vulkan. = main.cpp + imgui_impl_sdl.cpp + imgui_impl_vulkan.cpp +example_apple_metal/ + OSX & iOS + Metal. + It is based on the cross-platform game template provided with Xcode as of Xcode 9. + = game template + imgui_impl_osx.mm + imgui_impl_metal.mm + +example_apple_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 8feda89d..00000000 --- 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_apple_metal/README.md b/examples/example_apple_metal/README.md new file mode 100644 index 00000000..d43b4925 --- /dev/null +++ b/examples/example_apple_metal/README.md @@ -0,0 +1,6 @@ +# iOS / OSX Metal example + +## Introduction + +This example shows how to render ImGui with Metal. It is based on the cross-platform game template provided with Xcode as of Xcode 9. + diff --git a/examples/example_apple_metal/Shared/AppDelegate.h b/examples/example_apple_metal/Shared/AppDelegate.h new file mode 100644 index 00000000..c4632b1f --- /dev/null +++ b/examples/example_apple_metal/Shared/AppDelegate.h @@ -0,0 +1,19 @@ + +#import + +#if TARGET_OS_IPHONE + +#import + +@interface AppDelegate : UIResponder +@property (strong, nonatomic) UIWindow *window; +@end + +#else + +#import + +@interface AppDelegate : NSObject +@end + +#endif diff --git a/examples/example_apple_metal/Shared/AppDelegate.m b/examples/example_apple_metal/Shared/AppDelegate.m new file mode 100644 index 00000000..eabb44c1 --- /dev/null +++ b/examples/example_apple_metal/Shared/AppDelegate.m @@ -0,0 +1,12 @@ + +#import "AppDelegate.h" + +@implementation AppDelegate + +#if TARGET_OS_OSX +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { + return YES; +} +#endif + +@end diff --git a/examples/example_apple_metal/Shared/Renderer.h b/examples/example_apple_metal/Shared/Renderer.h new file mode 100644 index 00000000..f324915c --- /dev/null +++ b/examples/example_apple_metal/Shared/Renderer.h @@ -0,0 +1,9 @@ + +#import + +@interface Renderer : NSObject + +-(nonnull instancetype)initWithView:(nonnull MTKView *)view; + +@end + diff --git a/examples/example_apple_metal/Shared/Renderer.mm b/examples/example_apple_metal/Shared/Renderer.mm new file mode 100644 index 00000000..2f62ed17 --- /dev/null +++ b/examples/example_apple_metal/Shared/Renderer.mm @@ -0,0 +1,132 @@ + +#import "Renderer.h" +#import + +#include "imgui.h" +#include "imgui_impl_metal.h" + +#if TARGET_OS_OSX +#include "imgui_impl_osx.h" +#endif + +@interface Renderer () +@property (nonatomic, strong) id device; +@property (nonatomic, strong) id commandQueue; +@end + +@implementation Renderer + +-(nonnull instancetype)initWithView:(nonnull MTKView *)view; +{ + self = [super init]; + if(self) + { + _device = view.device; + _commandQueue = [_device newCommandQueue]; + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + (void)ImGui::GetIO(); + + ImGui_ImplMetal_Init(_device); + + ImGui::StyleColorsDark(); + } + + return self; +} + +- (void)drawInMTKView:(MTKView *)view +{ + ImGuiIO &io = ImGui::GetIO(); + io.DisplaySize.x = view.bounds.size.width; + io.DisplaySize.y = view.bounds.size.height; + +#if TARGET_OS_OSX + CGFloat framebufferScale = view.window.screen.backingScaleFactor ?: NSScreen.mainScreen.backingScaleFactor; +#else + CGFloat framebufferScale = view.window.screen.scale ?: UIScreen.mainScreen.scale; +#endif + io.DisplayFramebufferScale = ImVec2(framebufferScale, framebufferScale); + + io.DeltaTime = 1 / float(view.preferredFramesPerSecond ?: 60); + + id commandBuffer = [self.commandQueue commandBuffer]; + + static bool show_demo_window = true; + static bool show_another_window = false; + static float clear_color[4] = { 0.28f, 0.36f, 0.5f, 1.0f }; + + MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor; + if(renderPassDescriptor != nil) + { + renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]); + + // Here, you could do additional rendering work, including other passes as necessary. + + id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + + [renderEncoder pushDebugGroup:@"Draw ImGui"]; + + ImGui_ImplMetal_NewFrame(renderPassDescriptor); +#if TARGET_OS_OSX + ImGui_ImplOSX_NewFrame(view); +#endif + ImGui::NewFrame(); + + { + 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) + { + // 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::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::ShowDemoWindow(&show_demo_window); + } + + ImGui::Render(); + ImDrawData *drawData = ImGui::GetDrawData(); + ImGui_ImplMetal_RenderDrawData(drawData, commandBuffer, renderEncoder); + + [renderEncoder popDebugGroup]; + + [renderEncoder endEncoding]; + + [commandBuffer presentDrawable:view.currentDrawable]; + } + + [commandBuffer commit]; +} + +- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size +{ +} + +@end diff --git a/examples/example_apple_metal/Shared/ViewController.h b/examples/example_apple_metal/Shared/ViewController.h new file mode 100644 index 00000000..a8aade13 --- /dev/null +++ b/examples/example_apple_metal/Shared/ViewController.h @@ -0,0 +1,20 @@ + +#import +#import +#import "Renderer.h" + +#if TARGET_OS_IPHONE + +#import + +@interface ViewController : UIViewController +@end + +#else + +#import + +@interface ViewController : NSViewController +@end + +#endif diff --git a/examples/example_apple_metal/Shared/ViewController.mm b/examples/example_apple_metal/Shared/ViewController.mm new file mode 100644 index 00000000..6a9236c4 --- /dev/null +++ b/examples/example_apple_metal/Shared/ViewController.mm @@ -0,0 +1,130 @@ + +#import "ViewController.h" +#import "Renderer.h" +#include "imgui.h" + +#if TARGET_OS_OSX +#include "imgui_impl_osx.h" +#endif + +@interface ViewController () +@property (nonatomic, readonly) MTKView *mtkView; +@property (nonatomic, strong) Renderer *renderer; +@end + +@implementation ViewController + +- (MTKView *)mtkView { + return (MTKView *)self.view; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.mtkView.device = MTLCreateSystemDefaultDevice(); + + if (!self.mtkView.device) { + NSLog(@"Metal is not supported"); + abort(); + } + + self.renderer = [[Renderer alloc] initWithView:self.mtkView]; + + [self.renderer mtkView:self.mtkView drawableSizeWillChange:self.mtkView.bounds.size]; + + self.mtkView.delegate = self.renderer; + +#if TARGET_OS_OSX + // Add a tracking area in order to receive mouse events whenever the mouse is within the bounds of our view + NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect + options:NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways + owner:self + userInfo:nil]; + [self.view addTrackingArea:trackingArea]; + + // If we want to receive key events, we either need to be in the responder chain of the key view, + // or else we can install a local monitor. The consequence of this heavy-handed approach is that + // we receive events for all controls, not just ImGui widgets. If we had native controls in our + // window, we'd want to be much more careful than just ingesting the complete event stream, though + // we do make an effort to be good citizens by passing along events when ImGui doesn't want to capture. + NSEventMask eventMask = NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged | NSEventTypeScrollWheel; + [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event) { + BOOL wantsCapture = ImGui_ImplOSX_HandleEvent(event, self.view); + if (event.type == NSEventTypeKeyDown && wantsCapture) { + return nil; + } else { + return event; + } + + }]; + + ImGui_ImplOSX_Init(); +#endif +} + +#if TARGET_OS_OSX + +- (void)mouseMoved:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)mouseDown:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)mouseUp:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)mouseDragged:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)scrollWheel:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +#elif TARGET_OS_IOS + +// This touch mapping is super cheesy/hacky. We treat any touch on the screen +// as if it were a depressed left mouse button, and we don't bother handling +// multitouch correctly at all. This causes the "cursor" to behave very erratically +// when there are multiple active touches. But for demo purposes, single-touch +// interaction actually works surprisingly well. +- (void)updateIOWithTouchEvent:(UIEvent *)event { + UITouch *anyTouch = event.allTouches.anyObject; + CGPoint touchLocation = [anyTouch locationInView:self.view]; + ImGuiIO &io = ImGui::GetIO(); + io.MousePos = ImVec2(touchLocation.x, touchLocation.y); + + BOOL hasActiveTouch = NO; + for (UITouch *touch in event.allTouches) { + if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled) { + hasActiveTouch = YES; + break; + } + } + io.MouseDown[0] = hasActiveTouch; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [self updateIOWithTouchEvent:event]; +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + [self updateIOWithTouchEvent:event]; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + [self updateIOWithTouchEvent:event]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + [self updateIOWithTouchEvent:event]; +} + +#endif + +@end + diff --git a/examples/example_apple_metal/Shared/main.m b/examples/example_apple_metal/Shared/main.m new file mode 100644 index 00000000..cd8468a7 --- /dev/null +++ b/examples/example_apple_metal/Shared/main.m @@ -0,0 +1,23 @@ + +#import + +#if TARGET_OS_IPHONE + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} + +#else + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} + +#endif diff --git a/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj b/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj new file mode 100644 index 00000000..b1b6b4e7 --- /dev/null +++ b/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj @@ -0,0 +1,541 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 8307E7CC20E9F9C900473790 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7CB20E9F9C900473790 /* ViewController.mm */; }; + 8307E7CF20E9F9C900473790 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8307E7CD20E9F9C900473790 /* Main.storyboard */; }; + 8307E7DE20E9F9C900473790 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7DD20E9F9C900473790 /* AppDelegate.m */; }; + 8307E7E420E9F9C900473790 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8307E7E220E9F9C900473790 /* Main.storyboard */; }; + 8307E7E720E9F9C900473790 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7E620E9F9C900473790 /* main.m */; }; + 8307E7E820E9F9C900473790 /* Renderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7BC20E9F9C700473790 /* Renderer.mm */; }; + 8307E7E920E9F9C900473790 /* Renderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7BC20E9F9C700473790 /* Renderer.mm */; }; + 836D2A2E20EE208E0098E909 /* imgui_impl_osx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 836D2A2D20EE208E0098E909 /* imgui_impl_osx.mm */; }; + 836D2A3020EE4A180098E909 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 836D2A2F20EE4A180098E909 /* Default-568h@2x.png */; }; + 836D2A3220EE4A900098E909 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 836D2A3120EE4A900098E909 /* Launch Screen.storyboard */; }; + 83BBE9DE20EB3FFC00295997 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7E620E9F9C900473790 /* main.m */; }; + 83BBE9DF20EB40AE00295997 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7DD20E9F9C900473790 /* AppDelegate.m */; }; + 83BBE9E020EB42D000295997 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7CB20E9F9C900473790 /* ViewController.mm */; }; + 83BBE9E520EB46B900295997 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9E420EB46B900295997 /* Metal.framework */; }; + 83BBE9E720EB46BD00295997 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9E620EB46BD00295997 /* MetalKit.framework */; }; + 83BBE9E920EB46C100295997 /* ModelIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9E820EB46C100295997 /* ModelIO.framework */; }; + 83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EA20EB471700295997 /* MetalKit.framework */; }; + 83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EB20EB471700295997 /* Metal.framework */; }; + 83BBE9EF20EB471C00295997 /* ModelIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EE20EB471C00295997 /* ModelIO.framework */; }; + 83BBE9FE20EB54D800295997 /* imgui_impl_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83BBE9FD20EB54D800295997 /* imgui_impl_metal.mm */; }; + 83BBE9FF20EB54D800295997 /* imgui_impl_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83BBE9FD20EB54D800295997 /* imgui_impl_metal.mm */; }; + 83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0120EB54E700295997 /* imgui_draw.cpp */; }; + 83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0120EB54E700295997 /* imgui_draw.cpp */; }; + 83BBEA0720EB54E700295997 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0220EB54E700295997 /* imgui_demo.cpp */; }; + 83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0220EB54E700295997 /* imgui_demo.cpp */; }; + 83BBEA0920EB54E700295997 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0320EB54E700295997 /* imgui.cpp */; }; + 83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0320EB54E700295997 /* imgui.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 8307E7BB20E9F9C700473790 /* Renderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Renderer.h; sourceTree = ""; }; + 8307E7BC20E9F9C700473790 /* Renderer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Renderer.mm; sourceTree = ""; }; + 8307E7C420E9F9C900473790 /* example_apple_metal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_apple_metal.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8307E7CA20E9F9C900473790 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 8307E7CB20E9F9C900473790 /* ViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = ""; }; + 8307E7CE20E9F9C900473790 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 8307E7D320E9F9C900473790 /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; + 8307E7DA20E9F9C900473790 /* example_apple_metal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_apple_metal.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8307E7DC20E9F9C900473790 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 8307E7DD20E9F9C900473790 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 8307E7E320E9F9C900473790 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 8307E7E520E9F9C900473790 /* Info-macOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-macOS.plist"; sourceTree = ""; }; + 8307E7E620E9F9C900473790 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 836D2A2C20EE208D0098E909 /* imgui_impl_osx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_osx.h; path = ../../imgui_impl_osx.h; sourceTree = ""; }; + 836D2A2D20EE208E0098E909 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../../imgui_impl_osx.mm; sourceTree = ""; }; + 836D2A2F20EE4A180098E909 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + 836D2A3120EE4A900098E909 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; + 83BBE9E420EB46B900295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/Metal.framework; sourceTree = DEVELOPER_DIR; }; + 83BBE9E620EB46BD00295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/MetalKit.framework; sourceTree = DEVELOPER_DIR; }; + 83BBE9E820EB46C100295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/ModelIO.framework; sourceTree = DEVELOPER_DIR; }; + 83BBE9EA20EB471700295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; + 83BBE9EB20EB471700295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; + 83BBE9EE20EB471C00295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = System/Library/Frameworks/ModelIO.framework; sourceTree = SDKROOT; }; + 83BBE9FC20EB54D800295997 /* imgui_impl_metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_metal.h; path = ../../imgui_impl_metal.h; sourceTree = ""; }; + 83BBE9FD20EB54D800295997 /* imgui_impl_metal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_metal.mm; path = ../../imgui_impl_metal.mm; sourceTree = ""; }; + 83BBEA0020EB54E700295997 /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 83BBEA0120EB54E700295997 /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 83BBEA0220EB54E700295997 /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../imgui_demo.cpp; sourceTree = ""; }; + 83BBEA0320EB54E700295997 /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 83BBEA0420EB54E700295997 /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8307E7C120E9F9C900473790 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 83BBE9E920EB46C100295997 /* ModelIO.framework in Frameworks */, + 83BBE9E720EB46BD00295997 /* MetalKit.framework in Frameworks */, + 83BBE9E520EB46B900295997 /* Metal.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8307E7D720E9F9C900473790 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 83BBE9EF20EB471C00295997 /* ModelIO.framework in Frameworks */, + 83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */, + 83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8307E7B520E9F9C700473790 = { + isa = PBXGroup; + children = ( + 83BBE9F020EB544400295997 /* imgui */, + 8307E7BA20E9F9C700473790 /* Shared */, + 8307E7C620E9F9C900473790 /* iOS */, + 8307E7DB20E9F9C900473790 /* macOS */, + 8307E7C520E9F9C900473790 /* Products */, + 83BBE9E320EB46B800295997 /* Frameworks */, + ); + sourceTree = ""; + }; + 8307E7BA20E9F9C700473790 /* Shared */ = { + isa = PBXGroup; + children = ( + 83BBE9FC20EB54D800295997 /* imgui_impl_metal.h */, + 83BBE9FD20EB54D800295997 /* imgui_impl_metal.mm */, + 836D2A2C20EE208D0098E909 /* imgui_impl_osx.h */, + 836D2A2D20EE208E0098E909 /* imgui_impl_osx.mm */, + 8307E7DC20E9F9C900473790 /* AppDelegate.h */, + 8307E7DD20E9F9C900473790 /* AppDelegate.m */, + 8307E7BB20E9F9C700473790 /* Renderer.h */, + 8307E7BC20E9F9C700473790 /* Renderer.mm */, + 8307E7CA20E9F9C900473790 /* ViewController.h */, + 8307E7CB20E9F9C900473790 /* ViewController.mm */, + 8307E7E620E9F9C900473790 /* main.m */, + ); + path = Shared; + sourceTree = ""; + }; + 8307E7C520E9F9C900473790 /* Products */ = { + isa = PBXGroup; + children = ( + 8307E7C420E9F9C900473790 /* example_apple_metal.app */, + 8307E7DA20E9F9C900473790 /* example_apple_metal.app */, + ); + name = Products; + sourceTree = ""; + }; + 8307E7C620E9F9C900473790 /* iOS */ = { + isa = PBXGroup; + children = ( + 836D2A2F20EE4A180098E909 /* Default-568h@2x.png */, + 8307E7CD20E9F9C900473790 /* Main.storyboard */, + 8307E7D320E9F9C900473790 /* Info-iOS.plist */, + 836D2A3120EE4A900098E909 /* Launch Screen.storyboard */, + ); + path = iOS; + sourceTree = ""; + }; + 8307E7DB20E9F9C900473790 /* macOS */ = { + isa = PBXGroup; + children = ( + 8307E7E220E9F9C900473790 /* Main.storyboard */, + 8307E7E520E9F9C900473790 /* Info-macOS.plist */, + ); + path = macOS; + sourceTree = ""; + }; + 83BBE9E320EB46B800295997 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 83BBE9EE20EB471C00295997 /* ModelIO.framework */, + 83BBE9EB20EB471700295997 /* Metal.framework */, + 83BBE9EA20EB471700295997 /* MetalKit.framework */, + 83BBE9E820EB46C100295997 /* ModelIO.framework */, + 83BBE9E620EB46BD00295997 /* MetalKit.framework */, + 83BBE9E420EB46B900295997 /* Metal.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 83BBE9F020EB544400295997 /* imgui */ = { + isa = PBXGroup; + children = ( + 83BBEA0420EB54E700295997 /* imconfig.h */, + 83BBEA0020EB54E700295997 /* imgui.h */, + 83BBEA0220EB54E700295997 /* imgui_demo.cpp */, + 83BBEA0120EB54E700295997 /* imgui_draw.cpp */, + 83BBEA0320EB54E700295997 /* imgui.cpp */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8307E7C320E9F9C900473790 /* example_apple_metal_ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8307E7F020E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_ios" */; + buildPhases = ( + 8307E7C020E9F9C900473790 /* Sources */, + 8307E7C120E9F9C900473790 /* Frameworks */, + 8307E7C220E9F9C900473790 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = example_apple_metal_ios; + productName = "imguiex iOS"; + productReference = 8307E7C420E9F9C900473790 /* example_apple_metal.app */; + productType = "com.apple.product-type.application"; + }; + 8307E7D920E9F9C900473790 /* example_apple_metal_macos */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8307E7F320E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_macos" */; + buildPhases = ( + 8307E7D620E9F9C900473790 /* Sources */, + 8307E7D720E9F9C900473790 /* Frameworks */, + 8307E7D820E9F9C900473790 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = example_apple_metal_macos; + productName = "imguiex macOS"; + productReference = 8307E7DA20E9F9C900473790 /* example_apple_metal.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8307E7B620E9F9C700473790 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0940; + ORGANIZATIONNAME = "Warren Moore"; + TargetAttributes = { + 8307E7C320E9F9C900473790 = { + CreatedOnToolsVersion = 9.4.1; + }; + 8307E7D920E9F9C900473790 = { + CreatedOnToolsVersion = 9.4.1; + }; + }; + }; + buildConfigurationList = 8307E7B920E9F9C700473790 /* Build configuration list for PBXProject "example_apple_metal" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 8307E7B520E9F9C700473790; + productRefGroup = 8307E7C520E9F9C900473790 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8307E7C320E9F9C900473790 /* example_apple_metal_ios */, + 8307E7D920E9F9C900473790 /* example_apple_metal_macos */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8307E7C220E9F9C900473790 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 836D2A3220EE4A900098E909 /* Launch Screen.storyboard in Resources */, + 8307E7CF20E9F9C900473790 /* Main.storyboard in Resources */, + 836D2A3020EE4A180098E909 /* Default-568h@2x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8307E7D820E9F9C900473790 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8307E7E420E9F9C900473790 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8307E7C020E9F9C900473790 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8307E7E820E9F9C900473790 /* Renderer.mm in Sources */, + 8307E7CC20E9F9C900473790 /* ViewController.mm in Sources */, + 83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */, + 83BBE9DF20EB40AE00295997 /* AppDelegate.m in Sources */, + 83BBEA0920EB54E700295997 /* imgui.cpp in Sources */, + 83BBEA0720EB54E700295997 /* imgui_demo.cpp in Sources */, + 83BBE9FE20EB54D800295997 /* imgui_impl_metal.mm in Sources */, + 83BBE9DE20EB3FFC00295997 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8307E7D620E9F9C900473790 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 83BBE9E020EB42D000295997 /* ViewController.mm in Sources */, + 8307E7E920E9F9C900473790 /* Renderer.mm in Sources */, + 83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */, + 8307E7E720E9F9C900473790 /* main.m in Sources */, + 83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */, + 83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */, + 83BBE9FF20EB54D800295997 /* imgui_impl_metal.mm in Sources */, + 836D2A2E20EE208E0098E909 /* imgui_impl_osx.mm in Sources */, + 8307E7DE20E9F9C900473790 /* AppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 8307E7CD20E9F9C900473790 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 8307E7CE20E9F9C900473790 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 8307E7E220E9F9C900473790 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 8307E7E320E9F9C900473790 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 8307E7EE20E9F9C900473790 /* 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; + 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; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + }; + name = Debug; + }; + 8307E7EF20E9F9C900473790 /* 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; + 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; + MTL_ENABLE_DEBUG_INFO = NO; + }; + name = Release; + }; + 8307E7F120E9F9C900473790 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/iOS/Info-iOS.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-ios"; + PRODUCT_NAME = example_apple_metal; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 8307E7F220E9F9C900473790 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/iOS/Info-iOS.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-ios"; + PRODUCT_NAME = example_apple_metal; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8307E7F420E9F9C900473790 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/macOS/Info-macOS.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.13; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos"; + PRODUCT_NAME = example_apple_metal; + SDKROOT = macosx; + }; + name = Debug; + }; + 8307E7F520E9F9C900473790 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/macOS/Info-macOS.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.13; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos"; + PRODUCT_NAME = example_apple_metal; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8307E7B920E9F9C700473790 /* Build configuration list for PBXProject "example_apple_metal" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8307E7EE20E9F9C900473790 /* Debug */, + 8307E7EF20E9F9C900473790 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8307E7F020E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8307E7F120E9F9C900473790 /* Debug */, + 8307E7F220E9F9C900473790 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8307E7F320E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_macos" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8307E7F420E9F9C900473790 /* Debug */, + 8307E7F520E9F9C900473790 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8307E7B620E9F9C700473790 /* Project object */; +} diff --git a/examples/example_apple_metal/iOS/Base.lproj/Main.storyboard b/examples/example_apple_metal/iOS/Base.lproj/Main.storyboard new file mode 100644 index 00000000..24a4009e --- /dev/null +++ b/examples/example_apple_metal/iOS/Base.lproj/Main.storyboard @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/example_apple_metal/iOS/Default-568h@2x.png b/examples/example_apple_metal/iOS/Default-568h@2x.png new file mode 100644 index 00000000..e3ce940a Binary files /dev/null and b/examples/example_apple_metal/iOS/Default-568h@2x.png differ diff --git a/examples/example_apple_metal/iOS/Info-iOS.plist b/examples/example_apple_metal/iOS/Info-iOS.plist new file mode 100644 index 00000000..8d919d1e --- /dev/null +++ b/examples/example_apple_metal/iOS/Info-iOS.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + imgui + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + Launch Screen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + metal + + UIRequiresFullScreen + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortraitUpsideDown + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/example_apple_metal/iOS/Launch Screen.storyboard b/examples/example_apple_metal/iOS/Launch Screen.storyboard new file mode 100644 index 00000000..96047e1f --- /dev/null +++ b/examples/example_apple_metal/iOS/Launch Screen.storyboard @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/example_apple_metal/macOS/Base.lproj/Main.storyboard b/examples/example_apple_metal/macOS/Base.lproj/Main.storyboard new file mode 100644 index 00000000..cf414617 --- /dev/null +++ b/examples/example_apple_metal/macOS/Base.lproj/Main.storyboard @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/example_apple_metal/macOS/Info-macOS.plist b/examples/example_apple_metal/macOS/Info-macOS.plist new file mode 100644 index 00000000..52d99204 --- /dev/null +++ b/examples/example_apple_metal/macOS/Info-macOS.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + imgui + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2018 Warren Moore. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/examples/example_apple_opengl2/example_apple_opengl2.xcodeproj/project.pbxproj b/examples/example_apple_opengl2/example_apple_opengl2.xcodeproj/project.pbxproj new file mode 100644 index 00000000..a325e96d --- /dev/null +++ b/examples/example_apple_opengl2/example_apple_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_apple_opengl2/main.mm b/examples/example_apple_opengl2/main.mm new file mode 100644 index 00000000..a8f4d364 --- /dev/null +++ b/examples/example_apple_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); + ImGui::NewFrame(); + + // 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, self); } +-(void)keyDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } +-(void)flagsChanged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } +-(void)mouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } +-(void)mouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } +-(void)scrollWheel:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } + +@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:NSEventModifierFlagCommand]; + + 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::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_metal.h b/examples/imgui_impl_metal.h new file mode 100644 index 00000000..c4f958b4 --- /dev/null +++ b/examples/imgui_impl_metal.h @@ -0,0 +1,25 @@ +// ImGui Renderer for: Metal +// This needs to be used along with a Platform Binding (e.g. OSX) + +// Implemented features: +// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. + +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +@class MTLRenderPassDescriptor; +@protocol MTLDevice, MTLCommandBuffer, MTLRenderCommandEncoder; + +IMGUI_IMPL_API bool ImGui_ImplMetal_Init(id device); +IMGUI_IMPL_API void ImGui_ImplMetal_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor *renderPassDescriptor); +IMGUI_IMPL_API void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, + id commandBuffer, + id commandEncoder); + +// Called by Init/NewFrame/Shutdown +IMGUI_IMPL_API bool ImGui_ImplMetal_CreateFontsTexture(id device); +IMGUI_IMPL_API void ImGui_ImplMetal_DestroyFontsTexture(); +IMGUI_IMPL_API bool ImGui_ImplMetal_CreateDeviceObjects(id device); +IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects(); diff --git a/examples/imgui_impl_metal.mm b/examples/imgui_impl_metal.mm new file mode 100644 index 00000000..8ee0643f --- /dev/null +++ b/examples/imgui_impl_metal.mm @@ -0,0 +1,490 @@ +// ImGui Renderer for: Metal +// This needs to be used along with a Platform Binding (e.g. OSX) + +// Implemented features: +// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. + +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-07-05: Metal: Added new Metal backend implementation. + +#include "imgui.h" +#include "imgui_impl_metal.h" + +#import +#import +#import + +#pragma mark - Support classes + +// A wrapper around a MTLBuffer object that knows the last time it was reused +@interface MetalBuffer : NSObject +@property (nonatomic, strong) id buffer; +@property (nonatomic, assign) NSTimeInterval lastReuseTime; +- (instancetype)initWithBuffer:(id)buffer; +@end + +// An object that encapsulates the data necessary to uniquely identify a +// render pipeline state. These are used as cache keys. +@interface FramebufferDescriptor : NSObject +@property (nonatomic, assign) unsigned long sampleCount; +@property (nonatomic, assign) MTLPixelFormat colorPixelFormat; +@property (nonatomic, assign) MTLPixelFormat depthPixelFormat; +@property (nonatomic, assign) MTLPixelFormat stencilPixelFormat; +- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor *)renderPassDescriptor; +@end + +// A singleton that stores long-lived objects that are needed by the Metal +// renderer backend. Stores the render pipeline state cache and the default +// font texture, and manages the reusable buffer cache. +@interface MetalContext : NSObject +@property (nonatomic, strong) id depthStencilState; +@property (nonatomic, strong) FramebufferDescriptor *framebufferDescriptor; // framebuffer descriptor for current frame; transient +@property (nonatomic, strong) NSMutableDictionary *renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors +@property (nonatomic, strong, nullable) id fontTexture; +@property (nonatomic, strong) NSMutableArray *bufferCache; +@property (nonatomic, assign) NSTimeInterval lastBufferCachePurge; +- (void)makeDeviceObjectsWithDevice:(id)device; +- (void)makeFontTextureWithDevice:(id)device; +- (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id)device; +- (void)enqueueReusableBuffer:(MetalBuffer *)buffer; +- (id)renderPipelineStateForFrameAndDevice:(id)device; +- (void)emptyRenderPipelineStateCache; +- (void)renderDrawData:(ImDrawData *)drawData + commandBuffer:(id)commandBuffer + commandEncoder:(id)commandEncoder; +@end + +static MetalContext *g_sharedMetalContext = nil; + +#pragma mark - ImGui API implementation + +bool ImGui_ImplMetal_Init(id device) +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + g_sharedMetalContext = [[MetalContext alloc] init]; + }); + + ImGui_ImplMetal_CreateDeviceObjects(device); + + return true; +} + +void ImGui_ImplMetal_Shutdown() +{ + ImGui_ImplMetal_DestroyDeviceObjects(); +} + +void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor *renderPassDescriptor) +{ + IM_ASSERT(g_sharedMetalContext != nil && "No Metal context. Did you call ImGui_ImplMetal_Init?"); + + g_sharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor]; +} + +// Metal Render function. +void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id commandBuffer, id commandEncoder) +{ + [g_sharedMetalContext renderDrawData:draw_data commandBuffer:commandBuffer commandEncoder:commandEncoder]; +} + +bool ImGui_ImplMetal_CreateFontsTexture(id device) +{ + [g_sharedMetalContext makeFontTextureWithDevice:device]; + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->TexID = (__bridge void *)g_sharedMetalContext.fontTexture; + + return (g_sharedMetalContext.fontTexture != nil); +} + +void ImGui_ImplMetal_DestroyFontsTexture() +{ + ImGuiIO& io = ImGui::GetIO(); + g_sharedMetalContext.fontTexture = nil; + io.Fonts->TexID = nullptr; +} + +bool ImGui_ImplMetal_CreateDeviceObjects(id device) +{ + [g_sharedMetalContext makeDeviceObjectsWithDevice:device]; + + ImGui_ImplMetal_CreateFontsTexture(device); + + return true; +} + +void ImGui_ImplMetal_DestroyDeviceObjects() +{ + ImGui_ImplMetal_DestroyFontsTexture(); + [g_sharedMetalContext emptyRenderPipelineStateCache]; +} + +#pragma mark - MetalBuffer implementation + +@implementation MetalBuffer +- (instancetype)initWithBuffer:(id)buffer { + if ((self = [super init])) { + _buffer = buffer; + _lastReuseTime = [NSDate date].timeIntervalSince1970; + } + return self; +} +@end + +#pragma mark - FramebufferDescriptor implementation + +@implementation FramebufferDescriptor +- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor *)renderPassDescriptor { + if ((self = [super init])) { + _sampleCount = renderPassDescriptor.colorAttachments[0].texture.sampleCount; + _colorPixelFormat = renderPassDescriptor.colorAttachments[0].texture.pixelFormat; + _depthPixelFormat = renderPassDescriptor.depthAttachment.texture.pixelFormat; + _stencilPixelFormat = renderPassDescriptor.stencilAttachment.texture.pixelFormat; + } + return self; +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + FramebufferDescriptor *copy = [[FramebufferDescriptor allocWithZone:zone] init]; + copy.sampleCount = self.sampleCount; + copy.colorPixelFormat = self.colorPixelFormat; + copy.depthPixelFormat = self.depthPixelFormat; + copy.stencilPixelFormat = self.stencilPixelFormat; + return copy; +} + +- (NSUInteger)hash { + NSUInteger sc = _sampleCount & 0x3; + NSUInteger cf = _colorPixelFormat & 0x3FF; + NSUInteger df = _depthPixelFormat & 0x3FF; + NSUInteger sf = _stencilPixelFormat & 0x3FF; + NSUInteger hash = (sf << 22) | (df << 12) | (cf << 2) | sc; + return hash; +} + +- (BOOL)isEqual:(id)object { + FramebufferDescriptor *other = object; + if (![other isKindOfClass:[FramebufferDescriptor class]]) { + return NO; + } + return other.sampleCount == self.sampleCount && + other.colorPixelFormat == self.colorPixelFormat && + other.depthPixelFormat == self.depthPixelFormat && + other.stencilPixelFormat == self.stencilPixelFormat; +} + +@end + +#pragma mark - MetalContext implementation + +@implementation MetalContext +- (instancetype)init { + if ((self = [super init])) { + _renderPipelineStateCache = [NSMutableDictionary dictionary]; + _bufferCache = [NSMutableArray array]; + _lastBufferCachePurge = [NSDate date].timeIntervalSince1970; + } + return self; +} + +- (void)makeDeviceObjectsWithDevice:(id)device { + MTLDepthStencilDescriptor *depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init]; + depthStencilDescriptor.depthWriteEnabled = NO; + depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; + self.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor]; +} + +- (void)makeFontTextureWithDevice:(id)device { + ImGuiIO &io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm + width:width + height:height + mipmapped:NO]; + textureDescriptor.usage = MTLTextureUsageShaderRead; +#if TARGET_OS_OSX + textureDescriptor.storageMode = MTLStorageModeManaged; +#else + textureDescriptor.storageMode = MTLStorageModeShared; +#endif + id texture = [device newTextureWithDescriptor:textureDescriptor]; + [texture replaceRegion:MTLRegionMake2D(0, 0, width, height) mipmapLevel:0 withBytes:pixels bytesPerRow:width * 4]; + self.fontTexture = texture; +} + +- (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id)device { + NSTimeInterval now = [NSDate date].timeIntervalSince1970; + + // Purge old buffers that haven't been useful for a while + if (now - self.lastBufferCachePurge > 1.0) { + NSMutableArray *survivors = [NSMutableArray array]; + for (MetalBuffer *candidate in self.bufferCache) { + if (candidate.lastReuseTime > self.lastBufferCachePurge) { + [survivors addObject:candidate]; + } + } + self.bufferCache = [survivors mutableCopy]; + self.lastBufferCachePurge = now; + } + + // See if we have a buffer we can reuse + MetalBuffer *bestCandidate = nil; + for (MetalBuffer *candidate in self.bufferCache) { + if (candidate.buffer.length >= length && (bestCandidate == nil || bestCandidate.lastReuseTime > candidate.lastReuseTime)) { + bestCandidate = candidate; + } + } + + if (bestCandidate != nil) { + [self.bufferCache removeObject:bestCandidate]; + bestCandidate.lastReuseTime = now; + return bestCandidate; + } + + // No luck; make a new buffer + id backing = [device newBufferWithLength:length options:MTLResourceStorageModeShared]; + return [[MetalBuffer alloc] initWithBuffer:backing]; +} + +- (void)enqueueReusableBuffer:(MetalBuffer *)buffer { + [self.bufferCache addObject:buffer]; +} + +- (_Nullable id)renderPipelineStateForFrameAndDevice:(id)device { + // Try to retrieve a render pipeline state that is compatible with the framebuffer config for this frame + // Thie hit rate for this cache should be very near 100%. + id renderPipelineState = self.renderPipelineStateCache[self.framebufferDescriptor]; + + if (renderPipelineState == nil) { + // No luck; make a new render pipeline state + renderPipelineState = [self _renderPipelineStateForFramebufferDescriptor:self.framebufferDescriptor device:device]; + // Cache render pipeline state for later reuse + self.renderPipelineStateCache[self.framebufferDescriptor] = renderPipelineState; + } + + return renderPipelineState; +} + +- (id)_renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor *)descriptor device:(id)device +{ + NSError *error = nil; + + NSString *shaderSource = @"" + "#include \n" + "using namespace metal;\n" + "\n" + "struct Uniforms {\n" + " float4x4 projectionMatrix;\n" + "};\n" + "\n" + "struct VertexIn {\n" + " float2 position [[attribute(0)]];\n" + " float2 texCoords [[attribute(1)]];\n" + " uchar4 color [[attribute(2)]];\n" + "};\n" + "\n" + "struct VertexOut {\n" + " float4 position [[position]];\n" + " float2 texCoords;\n" + " float4 color;\n" + "};\n" + "\n" + "vertex VertexOut vertex_main(VertexIn in [[stage_in]],\n" + " constant Uniforms &uniforms [[buffer(1)]]) {\n" + " VertexOut out;\n" + " out.position = uniforms.projectionMatrix * float4(in.position, 0, 1);\n" + " out.texCoords = in.texCoords;\n" + " out.color = float4(in.color) / float4(255.0);\n" + " return out;\n" + "}\n" + "\n" + "fragment half4 fragment_main(VertexOut in [[stage_in]],\n" + " texture2d texture [[texture(0)]]) {\n" + " constexpr sampler linearSampler(coord::normalized, min_filter::linear, mag_filter::linear, mip_filter::linear);\n" + " half4 texColor = texture.sample(linearSampler, in.texCoords);\n" + " return half4(in.color) * texColor;\n" + "}\n"; + + id library = [device newLibraryWithSource:shaderSource options:nil error:&error]; + if (library == nil) { + NSLog(@"Error: failed to create Metal library: %@", error); + return nil; + } + + id vertexFunction = [library newFunctionWithName:@"vertex_main"]; + id fragmentFunction = [library newFunctionWithName:@"fragment_main"]; + + if (vertexFunction == nil || fragmentFunction == nil) { + NSLog(@"Error: failed to find Metal shader functions in library: %@", error); + return nil; + } + + MTLVertexDescriptor *vertexDescriptor = [MTLVertexDescriptor vertexDescriptor]; + vertexDescriptor.attributes[0].offset = IM_OFFSETOF(ImDrawVert, pos); + vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2; // position + vertexDescriptor.attributes[0].bufferIndex = 0; + vertexDescriptor.attributes[1].offset = IM_OFFSETOF(ImDrawVert, uv); + vertexDescriptor.attributes[1].format = MTLVertexFormatFloat2; // texCoords + vertexDescriptor.attributes[1].bufferIndex = 0; + vertexDescriptor.attributes[2].offset = IM_OFFSETOF(ImDrawVert, col); + vertexDescriptor.attributes[2].format = MTLVertexFormatUChar4; // color + vertexDescriptor.attributes[2].bufferIndex = 0; + vertexDescriptor.layouts[0].stepRate = 1; + vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex; + vertexDescriptor.layouts[0].stride = sizeof(ImDrawVert); + + MTLRenderPipelineDescriptor *pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; + pipelineDescriptor.vertexFunction = vertexFunction; + pipelineDescriptor.fragmentFunction = fragmentFunction; + pipelineDescriptor.vertexDescriptor = vertexDescriptor; + pipelineDescriptor.sampleCount = self.framebufferDescriptor.sampleCount; + pipelineDescriptor.colorAttachments[0].pixelFormat = self.framebufferDescriptor.colorPixelFormat; + pipelineDescriptor.colorAttachments[0].blendingEnabled = YES; + pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; + pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; + pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; + pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha; + pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; + pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; + pipelineDescriptor.depthAttachmentPixelFormat = self.framebufferDescriptor.depthPixelFormat; + pipelineDescriptor.stencilAttachmentPixelFormat = self.framebufferDescriptor.stencilPixelFormat; + + id renderPipelineState = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error]; + if (error != nil) { + NSLog(@"Error: failed to create Metal pipeline state: %@", error); + } + + return renderPipelineState; +} + +- (void)emptyRenderPipelineStateCache { + [self.renderPipelineStateCache removeAllObjects]; +} + +- (void)renderDrawData:(ImDrawData *)drawData + commandBuffer:(id)commandBuffer + commandEncoder:(id)commandEncoder +{ + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + ImGuiIO &io = ImGui::GetIO(); + int fb_width = (int)(drawData->DisplaySize.x * io.DisplayFramebufferScale.x); + int fb_height = (int)(drawData->DisplaySize.y * io.DisplayFramebufferScale.y); + if (fb_width <= 0 || fb_height <= 0 || drawData->CmdListsCount == 0) + return; + drawData->ScaleClipRects(io.DisplayFramebufferScale); + + [commandEncoder setCullMode:MTLCullModeNone]; + [commandEncoder setDepthStencilState:g_sharedMetalContext.depthStencilState]; + + // Setup viewport, orthographic projection matrix + // Our visible imgui space lies from draw_data->DisplayPps (top left) to + // draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps. + MTLViewport viewport = { .originX = 0.0, + .originY = 0.0, + .width = double(fb_width), + .height = double(fb_height), + .znear = 0.0, + .zfar = 1.0 }; + [commandEncoder setViewport:viewport]; + float L = drawData->DisplayPos.x; + float R = drawData->DisplayPos.x + drawData->DisplaySize.x; + float T = drawData->DisplayPos.y; + float B = drawData->DisplayPos.y + drawData->DisplaySize.y; + float N = viewport.znear; + float F = viewport.zfar; + const float ortho_projection[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, 1/(F-N), 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), N/(F-N), 1.0f }, + }; + + [commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1]; + + size_t vertexBufferLength = 0; + size_t indexBufferLength = 0; + for (int n = 0; n < drawData->CmdListsCount; n++) { + const ImDrawList* cmd_list = drawData->CmdLists[n]; + vertexBufferLength += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert); + indexBufferLength += cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx); + } + + MetalBuffer *vertexBuffer = [self dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device]; + MetalBuffer *indexBuffer = [self dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device]; + + id renderPipelineState = [self renderPipelineStateForFrameAndDevice:commandBuffer.device]; + [commandEncoder setRenderPipelineState:renderPipelineState]; + + [commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0]; + + size_t vertexBufferOffset = 0; + size_t indexBufferOffset = 0; + ImVec2 pos = drawData->DisplayPos; + for (int n = 0; n < drawData->CmdListsCount; n++) + { + const ImDrawList* cmd_list = drawData->CmdLists[n]; + ImDrawIdx idx_buffer_offset = 0; + + memcpy((char *)vertexBuffer.buffer.contents + vertexBufferOffset, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy((char *)indexBuffer.buffer.contents + indexBufferOffset, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + + [commandEncoder setVertexBufferOffset:vertexBufferOffset atIndex:0]; + + 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) + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y); + if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) + { + // Apply scissor/clipping rectangle + MTLScissorRect scissorRect = { .x = NSUInteger(clip_rect.x), + .y = NSUInteger(clip_rect.y), + .width = NSUInteger(clip_rect.z - clip_rect.x), + .height = NSUInteger(clip_rect.w - clip_rect.y) }; + [commandEncoder setScissorRect:scissorRect]; + + + // Bind texture, Draw + if (pcmd->TextureId != NULL) { + [commandEncoder setFragmentTexture:(__bridge id)(pcmd->TextureId) atIndex:0]; + } + [commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle + indexCount:pcmd->ElemCount + indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32 + indexBuffer:indexBuffer.buffer + indexBufferOffset:indexBufferOffset + idx_buffer_offset]; + } + } + idx_buffer_offset += pcmd->ElemCount * sizeof(ImDrawIdx); + } + + vertexBufferOffset += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert); + indexBufferOffset += cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx); + } + + __weak id weakSelf = self; + [commandBuffer addCompletedHandler:^(id) { + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf enqueueReusableBuffer:vertexBuffer]; + [weakSelf enqueueReusableBuffer:indexBuffer]; + }); + }]; +} + +@end diff --git a/examples/imgui_impl_osx.h b/examples/imgui_impl_osx.h new file mode 100644 index 00000000..1ae2cc01 --- /dev/null +++ b/examples/imgui_impl_osx.h @@ -0,0 +1,15 @@ +// ImGui Platform Binding for: OSX / Cocoa +// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan, Metal..) +// [BETA] Beta bindings, not well tested. If you want a portable application, prefer using the Glfw or SDL platform bindings on Mac. + +// Issues: +// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters].. +// [ ] Platform: Mouse cursor shapes and visibility are not supported (see end of https://github.com/glfw/glfw/issues/427) + +@class NSEvent; +@class NSView; + +IMGUI_API bool ImGui_ImplOSX_Init(); +IMGUI_API void ImGui_ImplOSX_Shutdown(); +IMGUI_API void ImGui_ImplOSX_NewFrame(NSView *_Nonnull view); +IMGUI_API bool ImGui_ImplOSX_HandleEvent(NSEvent *_Nonnull event, NSView *_Nullable view); diff --git a/examples/imgui_impl_osx.mm b/examples/imgui_impl_osx.mm new file mode 100644 index 00000000..cd242149 --- /dev/null +++ b/examples/imgui_impl_osx.mm @@ -0,0 +1,238 @@ +// ImGui Platform Binding for: OSX / Cocoa +// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan, Metal..) +// [BETA] Beta bindings, not well tested. If you want a portable application, prefer using the Glfw or SDL platform bindings on Mac. + +// Issues: +// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters].. +// [ ] Platform: Mouse cursor shapes and visibility are not supported (see end of https://github.com/glfw/glfw/issues/427) + +#include "imgui.h" +#include "imgui_impl_osx.h" +#import + +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-07-07: 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. + const int offset_for_function_keys = 256 - 0xF700; + io.KeyMap[ImGuiKey_Tab] = '\t'; + io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_RightArrow] = NSRightArrowFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_UpArrow] = NSUpArrowFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_DownArrow] = NSDownArrowFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_PageUp] = NSPageUpFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_PageDown] = NSPageDownFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_Home] = NSHomeFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_End] = NSEndFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_Insert] = NSInsertFunctionKey + offset_for_function_keys; + io.KeyMap[ImGuiKey_Delete] = NSDeleteFunctionKey + offset_for_function_keys; + 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'; + + io.SetClipboardTextFn = [](void*, const char* str) -> void + { + NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil]; + [pasteboard setString:[NSString stringWithUTF8String:str] forType:NSPasteboardTypeString]; + }; + + io.GetClipboardTextFn = [](void*) -> const char* + { + NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; + NSString* available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:NSPasteboardTypeString]]; + if (![available isEqualToString:NSPasteboardTypeString]) + return NULL; + + NSString* string = [pasteboard stringForType:NSPasteboardTypeString]; + if (string == nil) + return NULL; + + const char* string_c = (const char*)[string UTF8String]; + size_t string_len = strlen(string_c); + static ImVector s_clipboard; + s_clipboard.resize((int)string_len + 1); + strcpy(s_clipboard.Data, string_c); + return s_clipboard.Data; + }; + + return true; +} + +void ImGui_ImplOSX_Shutdown() +{ +} + +void ImGui_ImplOSX_NewFrame(NSView* view) +{ + // Setup display size + ImGuiIO& io = ImGui::GetIO(); + 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; +} + +static int mapCharacterToKey(int c) +{ + if (c >= 'a' && c <= 'z') + return c - 'a' + 'A'; + if (c == 25) // SHIFT+TAB -> TAB + return 9; + if (c >= 0 && c < 256) + return c; + if (c >= 0xF700 && c < 0xF700 + 256) + return c - 0xF700 + 256; + return -1; +} + +static void resetKeys() +{ + ImGuiIO& io = ImGui::GetIO(); + for (int n = 0; n < IM_ARRAYSIZE(io.KeysDown); n++) + io.KeysDown[n] = false; +} + +bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) +{ + ImGuiIO& io = ImGui::GetIO(); + + if (event.type == NSEventTypeLeftMouseDown || event.type == NSEventTypeRightMouseDown || event.type == NSEventTypeOtherMouseDown) + { + int button = (int)[event buttonNumber]; + if (button >= 0 && button < IM_ARRAYSIZE(io.MouseDown)) + io.MouseDown[button] = true; + return io.WantCaptureMouse; + } + + if (event.type == NSEventTypeLeftMouseUp || event.type == NSEventTypeRightMouseUp || event.type == NSEventTypeOtherMouseUp) + { + int button = (int)[event buttonNumber]; + if (button >= 0 && button < IM_ARRAYSIZE(io.MouseDown)) + io.MouseDown[button] = false; + return io.WantCaptureMouse; + } + + if (event.type == NSEventTypeMouseMoved || event.type == NSEventTypeLeftMouseDragged) + { + NSPoint mousePoint = event.locationInWindow; + mousePoint = [view convertPoint:mousePoint fromView:nil]; + mousePoint = NSMakePoint(mousePoint.x, view.bounds.size.height - mousePoint.y); + io.MousePos = ImVec2(mousePoint.x, mousePoint.y); + } + + 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; + } + + // FIXME: All the key handling is wrong and broken. Refer to GLFW's cocoa_init.mm and cocoa_window.mm. + if (event.type == NSEventTypeKeyDown) + { + NSString* str = [event characters]; + int len = (int)[str length]; + for (int i = 0; i < len; i++) + { + int c = [str characterAtIndex:i]; + if (c < 0xF700 && !io.KeyCtrl) + io.AddInputCharacter(c); + + // We must reset in case we're pressing a sequence of special keys while keeping the command pressed + int key = mapCharacterToKey(c); + if (key != -1 && key < 256 && !io.KeyCtrl) + resetKeys(); + if (key != -1) + io.KeysDown[key] = 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 c = [str characterAtIndex:i]; + int key = mapCharacterToKey(c); + if (key != -1) + io.KeysDown[key] = false; + } + return io.WantCaptureKeyboard; + } + + if (event.type == NSEventTypeFlagsChanged) + { + ImGuiIO& io = ImGui::GetIO(); + unsigned int flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; + + bool oldKeyCtrl = io.KeyCtrl; + bool oldKeyShift = io.KeyShift; + bool oldKeyAlt = io.KeyAlt; + bool oldKeySuper = io.KeySuper; + io.KeyCtrl = flags & NSEventModifierFlagControl; + io.KeyShift = flags & NSEventModifierFlagShift; + io.KeyAlt = flags & NSEventModifierFlagOption; + io.KeySuper = flags & NSEventModifierFlagCommand; + + // We must reset them as we will not receive any keyUp event if they where pressed with a modifier + if ((oldKeyShift && !io.KeyShift) || (oldKeyCtrl && !io.KeyCtrl) || (oldKeyAlt && !io.KeyAlt) || (oldKeySuper && !io.KeySuper)) + resetKeys(); + return io.WantCaptureKeyboard; + } + + return false; +}