diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bd70928602a9..7c3f32c8505a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -62,6 +62,7 @@ Other Changes: - Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] - Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon] +- Examples: Apple+Metal: Consolidated/simplified to get closer to other examples. (#3543) [@warrenm] - Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md improved them. - Docs: Consistently renamed all occurences of "binding" and "back-end" to "backend" in comments and docs. diff --git a/examples/example_apple_metal/Shared/AppDelegate.h b/examples/example_apple_metal/Shared/AppDelegate.h deleted file mode 100644 index 94878d948e51..000000000000 --- a/examples/example_apple_metal/Shared/AppDelegate.h +++ /dev/null @@ -1,18 +0,0 @@ -#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 deleted file mode 100644 index 6947eb23b484..000000000000 --- a/examples/example_apple_metal/Shared/AppDelegate.m +++ /dev/null @@ -1,11 +0,0 @@ -#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 deleted file mode 100644 index 81fc6f547eb0..000000000000 --- a/examples/example_apple_metal/Shared/Renderer.h +++ /dev/null @@ -1,8 +0,0 @@ -#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 deleted file mode 100644 index c121f6923d35..000000000000 --- a/examples/example_apple_metal/Shared/Renderer.mm +++ /dev/null @@ -1,154 +0,0 @@ -#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]; - - // Setup Dear ImGui context - // FIXME: This example doesn't have proper cleanup... - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); (void)io; - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls - - // Setup Dear ImGui style - ImGui::StyleColorsDark(); - //ImGui::StyleColorsClassic(); - - // Setup Renderer backend - ImGui_ImplMetal_Init(_device); - - // 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 'docs/FONTS.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); - } - - 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]; - - // Our state (make them static = more or less global) as a convenience to keep the example terse. - 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:@"ImGui demo"]; - - // Start the Dear ImGui frame - ImGui_ImplMetal_NewFrame(renderPassDescriptor); -#if TARGET_OS_OSX - ImGui_ImplOSX_NewFrame(view); -#endif - ImGui::NewFrame(); - - // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). - if (show_demo_window) - ImGui::ShowDemoWindow(&show_demo_window); - - // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window. - { - static float f = 0.0f; - static int counter = 0; - - ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. - - ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) - ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state - ImGui::Checkbox("Another Window", &show_another_window); - - 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 - - if (ImGui::Button("Button")) // Buttons return true when clicked (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); - ImGui::End(); - } - - // 3. Show another simple window. - if (show_another_window) - { - ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) - ImGui::Text("Hello from another window!"); - if (ImGui::Button("Close Me")) - show_another_window = false; - ImGui::End(); - } - - // Rendering - 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 deleted file mode 100644 index 137f93e1304f..000000000000 --- a/examples/example_apple_metal/Shared/ViewController.h +++ /dev/null @@ -1,19 +0,0 @@ -#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 deleted file mode 100644 index 3c79cc1c4beb..000000000000 --- a/examples/example_apple_metal/Shared/ViewController.mm +++ /dev/null @@ -1,153 +0,0 @@ -#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 Dear 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 Dear 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)rightMouseDown:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)otherMouseDown:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)mouseUp:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)rightMouseUp:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)otherMouseUp:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)mouseDragged:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)rightMouseDragged:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)otherMouseDragged:(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 deleted file mode 100644 index 15938a906e8b..000000000000 --- a/examples/example_apple_metal/Shared/main.m +++ /dev/null @@ -1,22 +0,0 @@ -#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 index 38c45cfd4bf0..f382520f785c 100644 --- a/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj +++ b/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj @@ -9,27 +9,19 @@ /* Begin PBXBuildFile section */ 07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; }; 07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; }; - 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 */; }; + 8309BD8F253CCAAA0045E2A1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */; }; + 8309BDA5253CCC070045E2A1 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDA0253CCBC10045E2A1 /* main.mm */; }; + 8309BDA8253CCC080045E2A1 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDA0253CCBC10045E2A1 /* main.mm */; }; + 8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */; }; + 8309BDBE253CCCB60045E2A1 /* imgui_impl_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */; }; + 8309BDBF253CCCB60045E2A1 /* imgui_impl_osx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */; }; + 8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */; }; + 8309BDFC253CDAB30045E2A1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */; }; + 8309BE04253CDAB60045E2A1 /* MainMenu.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */; }; 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 */; }; @@ -41,31 +33,23 @@ /* Begin PBXFileReference section */ 07A82ED62139413C0078D120 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = ""; }; 07A82ED72139413C0078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = ""; }; - 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 = ../../../backends/imgui_impl_osx.h; sourceTree = ""; }; - 836D2A2D20EE208E0098E909 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../../../backends/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 = ""; }; + 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 8309BDA0253CCBC10045E2A1 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; + 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_metal.mm; path = ../../backends/imgui_impl_metal.mm; sourceTree = ""; }; + 8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../../backends/imgui_impl_osx.mm; sourceTree = ""; }; + 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + 8309BDF8253CDAAE0045E2A1 /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; + 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = MainMenu.storyboard; sourceTree = ""; }; + 8309BDFB253CDAAE0045E2A1 /* Info-macOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-macOS.plist"; 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 = ../../../backends/imgui_impl_metal.h; sourceTree = ""; }; - 83BBE9FD20EB54D800295997 /* imgui_impl_metal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_metal.mm; path = ../../../backends/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 = ""; }; @@ -78,7 +62,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 83BBE9E920EB46C100295997 /* ModelIO.framework in Frameworks */, + 8309BD8F253CCAAA0045E2A1 /* UIKit.framework in Frameworks */, 83BBE9E720EB46BD00295997 /* MetalKit.framework in Frameworks */, 83BBE9E520EB46B900295997 /* Metal.framework in Frameworks */, ); @@ -88,7 +72,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 83BBE9EF20EB471C00295997 /* ModelIO.framework in Frameworks */, + 8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */, 83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */, 83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */, ); @@ -101,57 +85,45 @@ isa = PBXGroup; children = ( 83BBE9F020EB544400295997 /* imgui */, - 8307E7BA20E9F9C700473790 /* Shared */, - 8307E7C620E9F9C900473790 /* iOS */, - 8307E7DB20E9F9C900473790 /* macOS */, + 8309BD9E253CCBA70045E2A1 /* example */, 8307E7C520E9F9C900473790 /* Products */, 83BBE9E320EB46B800295997 /* Frameworks */, ); sourceTree = ""; }; - 8307E7BA20E9F9C700473790 /* Shared */ = { + 8307E7C520E9F9C900473790 /* Products */ = { 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 */, + 8307E7C420E9F9C900473790 /* example_apple_metal.app */, + 8307E7DA20E9F9C900473790 /* example_apple_metal.app */, ); - path = Shared; + name = Products; sourceTree = ""; }; - 8307E7C520E9F9C900473790 /* Products */ = { + 8309BD9E253CCBA70045E2A1 /* example */ = { isa = PBXGroup; children = ( - 8307E7C420E9F9C900473790 /* example_apple_metal.app */, - 8307E7DA20E9F9C900473790 /* example_apple_metal.app */, + 8309BDF6253CDAAE0045E2A1 /* iOS */, + 8309BDF9253CDAAE0045E2A1 /* macOS */, + 8309BDA0253CCBC10045E2A1 /* main.mm */, ); - name = Products; + name = example; sourceTree = ""; }; - 8307E7C620E9F9C900473790 /* iOS */ = { + 8309BDF6253CDAAE0045E2A1 /* iOS */ = { isa = PBXGroup; children = ( - 836D2A2F20EE4A180098E909 /* Default-568h@2x.png */, - 8307E7CD20E9F9C900473790 /* Main.storyboard */, - 8307E7D320E9F9C900473790 /* Info-iOS.plist */, - 836D2A3120EE4A900098E909 /* Launch Screen.storyboard */, + 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */, + 8309BDF8253CDAAE0045E2A1 /* Info-iOS.plist */, ); path = iOS; sourceTree = ""; }; - 8307E7DB20E9F9C900473790 /* macOS */ = { + 8309BDF9253CDAAE0045E2A1 /* macOS */ = { isa = PBXGroup; children = ( - 8307E7E220E9F9C900473790 /* Main.storyboard */, - 8307E7E520E9F9C900473790 /* Info-macOS.plist */, + 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */, + 8309BDFB253CDAAE0045E2A1 /* Info-macOS.plist */, ); path = macOS; sourceTree = ""; @@ -159,6 +131,8 @@ 83BBE9E320EB46B800295997 /* Frameworks */ = { isa = PBXGroup; children = ( + 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */, + 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */, 83BBE9EE20EB471C00295997 /* ModelIO.framework */, 83BBE9EB20EB471700295997 /* Metal.framework */, 83BBE9EA20EB471700295997 /* MetalKit.framework */, @@ -172,6 +146,8 @@ 83BBE9F020EB544400295997 /* imgui */ = { isa = PBXGroup; children = ( + 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */, + 8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */, 83BBEA0420EB54E700295997 /* imconfig.h */, 83BBEA0320EB54E700295997 /* imgui.cpp */, 83BBEA0020EB54E700295997 /* imgui.h */, @@ -226,7 +202,7 @@ 8307E7B620E9F9C700473790 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0940; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = "Warren Moore"; TargetAttributes = { 8307E7C320E9F9C900473790 = { @@ -263,9 +239,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 836D2A3220EE4A900098E909 /* Launch Screen.storyboard in Resources */, - 8307E7CF20E9F9C900473790 /* Main.storyboard in Resources */, - 836D2A3020EE4A180098E909 /* Default-568h@2x.png in Resources */, + 8309BDFC253CDAB30045E2A1 /* LaunchScreen.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -273,7 +247,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8307E7E420E9F9C900473790 /* Main.storyboard in Resources */, + 8309BE04253CDAB60045E2A1 /* MainMenu.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -284,15 +258,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8307E7E820E9F9C900473790 /* Renderer.mm in Sources */, - 8307E7CC20E9F9C900473790 /* ViewController.mm in Sources */, + 8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal.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 */, 07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */, - 83BBE9DE20EB3FFC00295997 /* main.m in Sources */, + 8309BDA5253CCC070045E2A1 /* main.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -300,40 +271,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 83BBE9E020EB42D000295997 /* ViewController.mm in Sources */, - 8307E7E920E9F9C900473790 /* Renderer.mm in Sources */, + 8309BDBE253CCCB60045E2A1 /* imgui_impl_metal.mm in Sources */, + 8309BDBF253CCCB60045E2A1 /* imgui_impl_osx.mm in Sources */, 83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */, 07A82ED92139418F0078D120 /* imgui_widgets.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 */, + 8309BDA8253CCC080045E2A1 /* main.mm 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; @@ -361,6 +310,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -416,6 +366,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -451,6 +402,7 @@ PRODUCT_NAME = example_apple_metal; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**"; }; name = Debug; }; @@ -467,6 +419,7 @@ PRODUCT_NAME = example_apple_metal; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -484,6 +437,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos"; PRODUCT_NAME = example_apple_metal; SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**"; }; name = Debug; }; @@ -500,6 +454,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos"; PRODUCT_NAME = example_apple_metal; SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**"; }; name = Release; }; diff --git a/examples/example_apple_metal/iOS/Base.lproj/Main.storyboard b/examples/example_apple_metal/iOS/Base.lproj/Main.storyboard deleted file mode 100644 index 24a4009ef7d7..000000000000 --- a/examples/example_apple_metal/iOS/Base.lproj/Main.storyboard +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/example_apple_metal/iOS/Default-568h@2x.png b/examples/example_apple_metal/iOS/Default-568h@2x.png deleted file mode 100644 index e3ce940a36b6..000000000000 Binary files a/examples/example_apple_metal/iOS/Default-568h@2x.png and /dev/null differ diff --git a/examples/example_apple_metal/iOS/Info-iOS.plist b/examples/example_apple_metal/iOS/Info-iOS.plist index 8d919d1e50d8..93ef078d0738 100644 --- a/examples/example_apple_metal/iOS/Info-iOS.plist +++ b/examples/example_apple_metal/iOS/Info-iOS.plist @@ -21,9 +21,7 @@ LSRequiresIPhoneOS UILaunchStoryboardName - Launch Screen - UIMainStoryboardFile - Main + LaunchScreen UIRequiredDeviceCapabilities armv7 diff --git a/examples/example_apple_metal/iOS/Launch Screen.storyboard b/examples/example_apple_metal/iOS/LaunchScreen.storyboard similarity index 69% rename from examples/example_apple_metal/iOS/Launch Screen.storyboard rename to examples/example_apple_metal/iOS/LaunchScreen.storyboard index 96047e1fc755..12c52cfbf59b 100644 --- a/examples/example_apple_metal/iOS/Launch Screen.storyboard +++ b/examples/example_apple_metal/iOS/LaunchScreen.storyboard @@ -1,11 +1,9 @@ - - - - + + - + @@ -15,10 +13,10 @@ - + - + diff --git a/examples/example_apple_metal/macOS/Info-macOS.plist b/examples/example_apple_metal/macOS/Info-macOS.plist index 52d992048f9c..6f4a2b2366ea 100644 --- a/examples/example_apple_metal/macOS/Info-macOS.plist +++ b/examples/example_apple_metal/macOS/Info-macOS.plist @@ -22,10 +22,8 @@ 1 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2018 Warren Moore. All rights reserved. NSMainStoryboardFile - Main + MainMenu NSPrincipalClass NSApplication diff --git a/examples/example_apple_metal/macOS/Base.lproj/Main.storyboard b/examples/example_apple_metal/macOS/MainMenu.storyboard similarity index 68% rename from examples/example_apple_metal/macOS/Base.lproj/Main.storyboard rename to examples/example_apple_metal/macOS/MainMenu.storyboard index cf41461705af..38ad432b0f52 100644 --- a/examples/example_apple_metal/macOS/Base.lproj/Main.storyboard +++ b/examples/example_apple_metal/macOS/MainMenu.storyboard @@ -1,9 +1,8 @@ - + - - + @@ -16,8 +15,6 @@ - - @@ -90,41 +87,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/examples/example_apple_metal/main.mm b/examples/example_apple_metal/main.mm new file mode 100644 index 000000000000..ec6482eed260 --- /dev/null +++ b/examples/example_apple_metal/main.mm @@ -0,0 +1,378 @@ + +#import + +#if TARGET_OS_OSX +#import +#else +#import +#endif + +#import +#import + +#include "imgui.h" +#include "imgui_impl_metal.h" + +#if TARGET_OS_OSX +#include "imgui_impl_osx.h" + +@interface ViewController : NSViewController +@end +#else +@interface ViewController : UIViewController +@end +#endif + +@interface ViewController () +@property (nonatomic, readonly) MTKView *mtkView; +@property (nonatomic, strong) id device; +@property (nonatomic, strong) id commandQueue; +@end + +@implementation ViewController + +- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + + _device = MTLCreateSystemDefaultDevice(); + _commandQueue = [_device newCommandQueue]; + + if (!self.device) { + NSLog(@"Metal is not supported"); + abort(); + } + + // Setup Dear ImGui context + // FIXME: This example doesn't have proper cleanup... + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); + + // Setup Renderer backend + ImGui_ImplMetal_Init(_device); + + // 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 'docs/FONTS.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); + + return self; +} + +- (MTKView *)mtkView { + return (MTKView *)self.view; +} + +- (void)loadView { + self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 720)]; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.mtkView.device = self.device; + self.mtkView.delegate = self; + +#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 Dear 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 Dear 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 +} + +#pragma mark - Interaction + +#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)rightMouseDown:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)otherMouseDown:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)mouseUp:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)rightMouseUp:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)otherMouseUp:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)mouseDragged:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)rightMouseDragged:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)otherMouseDragged:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)scrollWheel:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +#else + +// 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 + +#pragma mark - MTKViewDelegate + +- (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]; + + // Our state (make them static = more or less global) as a convenience to keep the example terse. + 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:@"ImGui demo"]; + + // Start the Dear ImGui frame + ImGui_ImplMetal_NewFrame(renderPassDescriptor); +#if TARGET_OS_OSX + ImGui_ImplOSX_NewFrame(view); +#endif + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + 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 + + if (ImGui::Button("Button")) // Buttons return true when clicked (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); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + 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 + +#pragma mark - Application Delegate + +#if TARGET_OS_OSX + +@interface AppDelegate : NSObject +@property (nonatomic, strong) NSWindow *window; +@end + +@implementation AppDelegate + +- (instancetype)init { + if (self = [super init]) { + NSViewController *rootViewController = [[ViewController alloc] initWithNibName:nil bundle:nil]; + self.window = [[NSWindow alloc] initWithContentRect:NSZeroRect + styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable + backing:NSBackingStoreBuffered + defer:NO]; + self.window.contentViewController = rootViewController; + [self.window orderFront:self]; + [self.window center]; + [self.window becomeKeyWindow]; + } + return self; +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { + return YES; +} + +@end + +#else + +@interface AppDelegate : UIResponder +@property (strong, nonatomic) UIWindow *window; +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + UIViewController *rootViewController = [[ViewController alloc] init]; + self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; + return YES; +} + +@end + +#endif + +#pragma mark - main() + +#if TARGET_OS_OSX + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} + +#else + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} + +#endif